How to verify that Squid used as a reversed proxy is working? - proxy

We want to decrease the load in one of our web servers and we are running some tests with squid configured as a reverse proxy.
The configuration is in the remarks below:
http_port 80 accel defaultsite=original.server.com
cache_peer original.server.com parent 80 0 no-query originserver name=myAccel
acl our_sites dstdomain .contentpilot.net
http_access allow our_sites
cache_peer_access myAccel allow our_sites
cache_peer_access myAccel deny all
The situation we are having is that pretty much the server is returning TCP_MISS almost all the time.
1238022316.988 86 69.15.30.186 TCP_MISS/200 797 GET http://original.server.com/templates/site/images/topnav_givingback.gif - FIRST_UP_PARENT/myAccel -
1238022317.016 76 69.15.30.186 TCP_MISS/200 706 GET http://original.server.com/templates/site/images/topnav_diversity.gif - FIRST_UP_PARENT/myAccel -
1238022317.158 75 69.15.30.186 TCP_MISS/200 570 GET http://original.server.com/templates/site/images/topnav_careers.gif - FIRST_UP_PARENT/myAccel -
1238022317.344 75 69.15.30.186 TCP_MISS/200 2981 GET http://original.server.com/templates/site/js/home-search-personalization.js - FIRST_UP_PARENT/myAccel -
1238022317.414 85 69.15.30.186 TCP_MISS/200 400 GET http://original.server.com/templates/site/images/submenu_arrow.gif - FIRST_UP_PARENT/myAccel -
1238022317.807 75 69.15.30.186 TCP_MISS/200 2680 GET http://original.server.com/templates/site/js/homeMakeURL.js - FIRST_UP_PARENT/myAccel -
1238022318.666 1401 69.15.30.186 TCP_MISS/200 103167 GET http://original.server.com/portalresource/lookup/wosid/intelliun-2201-301/image2.jpg - FIRST_UP_PARENT/myAccel image/pjpeg
1238022319.057 1938 69.15.30.186 TCP_MISS/200 108021 GET http://original.server.com/portalresource/lookup/wosid/intelliun-2201-301/image1.jpg - FIRST_UP_PARENT/myAccel image/pjpeg
1238022319.367 83 69.15.30.186 TCP_MISS/200 870 GET http://original.server.com/templates/site/images/home_dots.gif - FIRST_UP_PARENT/myAccel -
1238022319.367 80 69.15.30.186 TCP_MISS/200 5052 GET http://original.server.com/templates/site/images/home_search.jpg - FIRST_UP_PARENT/myAccel -
1238022319.368 88 69.15.30.186 TCP_MISS/200 5144 GET http://original.server.com/templates/site/images/home_continue.jpg - FIRST_UP_PARENT/myAccel -
1238022319.368 76 69.15.30.186 TCP_MISS/200 412 GET http://original.server.com/templates/site/js/showFooterBar.js - FIRST_UP_PARENT/myAccel -
1238022319.377 100 69.15.30.186 TCP_MISS/200 399 GET http://original.server.com/templates/site/images/home_arrow.gif - FIRST_UP_PARENT/myAccel -
We already tried removing all the cache memory. Any ideas. Could it be that my web site is marking some of the content different each time even though it has not change since the last time it was requested by the proxy?

What headers is the origin server (web server) sending back with your content? In order to be cacheable by squid, I believe you generally have to specify either a Last-Modified or ETag in the response header. Web servers will typically do this automatically for static content, but if your content is being dynamically served (even if from a static source) then you have to ensure they are there, and handle request headers such as If-Modified-Since and If-None-Match.
Also, since I got pointed to this question by your subsequent question about sessions--- is there a "Vary" header coming out in the response? For example, "Vary: Cookie" tells caches that the content can vary according to the Cookie header in the request: so static content wants to have that removed. But your web server might be adding that to all requests if there is a session, regardless of the static/dynamic nature of the data being served.
In my experience, some experimentation with the HTTP headers to see what the effects are on caching is of great benefit: I remember finding that the solutions were not always obvious.

Examine the headers returned with wireshark or firebug in firefox (the latter is easier to prod around but the former will give you more low-level information if you end up needing that).
Look for these items in the Response Headers (click on an item in the `Net' view to expand it and see request and response headers):
Last-Modified date -> if not set to a sensible time in the past then it won't be cached
Etags -> if these change every time the same item is requested then it will be re-fetched
Cache-Control -> Requests from the client with max-age=0 will (I believe) request a fresh copy of the page each time
(edit) Expires header -> If this is set in the past (i.e. always expired) then squid will not cache it
As suggested by araqnid, the HTTP headers can make a huge difference to what the proxy will think it can cache. If your back-end is using apache then test that static files served without going via any PHP or other application layer are cacheable.
Also, check that the squid settings for maximum_object_size and minimum_object_size are set to sensible values (the defaults are 4Mb and 0kb, which should be fine), and maximum cache item ages are also set sensibly.
(See http://www.visolve.com/squid/squid30/cachesize.php#maximum_object_size for this and other settings)

Related

JMeter report shows 3 results for one request

I installed JMeter 5.3, created one thread group with 10/10/10 (users/rampup time/loop count), so I expect to get 100 requests executed total and see graph with one line which will show how long requests take, BUT I see that 300 requests were executed and my report dashboard looks like this:
SomeRequest 100 0 0.00% 1570.50 1118 1900 1684.50 1892.90 1900.00 1900.00 4.85 29.62 1.91
SomeRequest-0 100 0 0.00% 344.50 305 405 337.50 403.20 405.00 405.00 13.14 6.71 2.59
SomeRequest-1 100 0 0.00% 1225.30 812 1494 1345.50 1492.40 1494.00 1494.00 6.04 33.78 1.19
And graph shows 3 lines instead of one.
So my question: why do I see 3 lines instead of one? Why test was executed 3 times? Maybe I'm missing some global config property which is set to "3"?
There could be 2 possible reasons:
Your server redirects you somewhere so you see these extra requests as redirect targets (like from HTTP to HTTPS, from landing page to language-specific page, etc)
like here:
You have Retrieve all embedded resources option enabled on "Advanced" tab of the HTTP Request sampler so JMeter parses the response and downloads extra data like images, scripts, styles, fonts, etc.
Most probably the behaviour is valid, if you want to check the URL for the sub-requests you can run your test in GUI mode with Functional test mode option enabled on Test Plan level - this way you will be able to see the URLs for the secondary requests:

Strategies in reducing network delay from 500 milliseconds to 60-100 milliseconds

I am building an autocomplete functionality and realized the amount of time taken between the client and server is too high (in the range of 450-700ms)
My first stop was to check if this is result of server delay.
But as you can see these Nginx logs are almost always 0.001 milliseconds (request time is the last column). It’s hardly a cause of concern.
So it became very evident that I am losing time between the server and the client. My benchmarks are Google Instant's response times. Which almost often is in the range of 30-40 milliseconds. Magnitudes lower.
Although it’s easy to say that Google's has massive infrastructural capabilities to deliver at this speed, I wanted to push myself to learn if this is possible for someone who is not that level. If not 60 milliseconds, I want to shave off 100-150 milliseconds.
Here are some of the strategies I’ve managed to learn.
Enable httpd slowstart and initcwnd
Ensure SPDY if you are on https
Ensure results are http compressed
Etc.
What are the other things I can do here?
e.g
Does have a persistent connection help?
Should I reduce the response size dramatically?
Edit:
Here are the ping and traceroute numbers. The site is served via cloudflare from a Fremont Linode machine.
mymachine-Mac:c name$ ping site.com
PING site.com (160.158.244.92): 56 data bytes
64 bytes from 160.158.244.92: icmp_seq=0 ttl=58 time=95.557 ms
64 bytes from 160.158.244.92: icmp_seq=1 ttl=58 time=103.569 ms
64 bytes from 160.158.244.92: icmp_seq=2 ttl=58 time=95.679 ms
^C
--- site.com ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 95.557/98.268/103.569/3.748 ms
mymachine-Mac:c name$ traceroute site.com
traceroute: Warning: site.com has multiple addresses; using 160.158.244.92
traceroute to site.com (160.158.244.92), 64 hops max, 52 byte packets
1 192.168.1.1 (192.168.1.1) 2.393 ms 1.159 ms 1.042 ms
2 172.16.70.1 (172.16.70.1) 22.796 ms 64.531 ms 26.093 ms
3 abts-kk-static-ilp-241.11.181.122.airtel.in (122.181.11.241) 28.483 ms 21.450 ms 25.255 ms
4 aes-static-005.99.22.125.airtel.in (125.22.99.5) 30.558 ms 30.448 ms 40.344 ms
5 182.79.245.62 (182.79.245.62) 75.568 ms 101.446 ms 68.659 ms
6 13335.sgw.equinix.com (202.79.197.132) 84.201 ms 65.092 ms 56.111 ms
7 160.158.244.92 (160.158.244.92) 66.352 ms 69.912 ms 81.458 ms
mymachine-Mac:c name$ site.com (160.158.244.92): 56 data bytes
I may well be wrong, but personally I smell a rat. Your times aren't justified by your setup; I believe that your requests ought to run much faster.
If at all possible, generate a short query using curl and intercept it with tcpdump on both the client and the server.
It could be a bandwidth/concurrency problem on the hosting. Check out its diagnostic panel, or try estimating the traffic.
You can try and save a response query into a static file, then requesting that file (taking care as not to trigger the local browser cache...), to see whether the problem might be in processing the data (either server or client side).
Does this slowness affect every request, or only the autocomplete ones? If the latter, and no matter what nginx says, it might be some inefficiency/delay in recovering or formatting the autocompletion data for output.
Also, you can try and serve a static response bypassing nginx altogether, in case this is an issue with nginx (and for that matter: have you checked out nginx' error log?).
One approach I didn't see you mention is to use SSL sessions: you can add the following into your nginx conf to make sure that an SSL handshake (very expensive process) does not happen with every connection request:
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
See "HTTPS server optimizations" here:
http://nginx.org/en/docs/http/configuring_https_servers.html
I would recommend using New Relic if you aren't already. It is possible that the server-side code you have could be the issue. If you think that might be the issue, there are quite a few free code profiling tools.
You may want to consider an option to preload autocomplete options in the background while the page is rendered and then save a trie or whatever structure you use on the client in the local storage. When the user starts typing in the autocomplete field you would not need to send any requests to the server but instead query local storage.
Web SQL Database and IndexedDB introduce databases to the clientside.
Instead of the common pattern of posting data to the server via
XMLHttpRequest or form submission, you can leverage these clientside
databases. Decreasing HTTP requests is a primary target of all
performance engineers, so using these as a datastore can save many
trips via XHR or form posts back to the server. localStorage and
sessionStorage could be used in some cases, like capturing form
submission progress, and have seen to be noticeably faster than the
client-side database APIs.
For example, if you have a data grid component or an inbox with
hundreds of messages, storing the data locally in a database will save
you HTTP roundtrips when the user wishes to search, filter, or sort. A
list of friends or a text input autocomplete could be filtered on each
keystroke, making for a much more responsive user experience.
http://www.html5rocks.com/en/tutorials/speed/quick/#toc-databases

Rack::Cache/Rack::Etag 304

I use Rack:Etag to genereate proper etag values based on the response from the server and for development I use Rack::Cache to verify that that caching I expect to happen really does
But i have a slight predicament:
I send a request and get these headers back
Age →0
Cache-Control →public, max-age=10
Connection →keep-alive
Content-Length →4895
Content-Type →application/json; charset=UTF-8
Date →Wed, 02 Oct 2013 06:55:42 GMT
ETag →"dd65de99f4ce58f9de42992c4e263e80"
Server →thin 1.5.1 codename Straight Razor
X-Content-Digest →0879e41b0d8e9b351f517dd46823095e0e99abd8
X-Rack-Cache →stale, invalid, store
If i after 11 seconds send a new request with If-None-Match=dd65de99f4ce58f9de42992c4e263e80 then i expect to get a 304 but always get 200 with the above headers.
What am I missing ?
Could it be due to max-age directive being set to 10
When the max-age cache-control directive is present in a cached response, the response is stale if its current age is greater than the age value given (in seconds) at the time of a new request for that resource.
Although, did you already know that? As you tried after 11 secs!
I think the solution was to load the rack middleware as follows for coorect chaining
use Rack::Cache
use Rack::ConditionalGet
use Rack::ETag
And also send If-None-Match with "" around hash, which i think seems pretty fragile

How do I invalidate HTTP cache with the Location header?

On cache invalidation, the HTTP spec says:
Some HTTP methods MUST cause a cache to invalidate an entity. This is either the entity referred to by the Request-URI, or by the Location or Content-Location headers (if present).
I am trying to invalidate an entry in my cache through the use of the Location header, but it doesn't appear to be working. Here's my use case:
15:13:23.9988 | GET | folders/folder.34/contents - 200 (OK)
15:13:24.1318 | PUT | folders/folder.34/contents/test.docx - 201 (Created)
15:13:24.1548 | GET | folders/folder.34/contents - 200 (OK) (cached)
The response of (2) contains a Location header with the URI used in requests (1) and (3). I believe this should invalidate the cached entry for folders/folder.34/contents, but the response in (3) appears to be coming from cache anyway according to the HttpWebResponse.IsFromCache property.
I have tried numerous URI formats in the Location header, including:
Location: ../../../folders/folder.34/contents (and other assorted '../' counts)
Location: folders/folder.34/contents
Location: /folders/folder.34/contents
Location: http://myhostname/folders/folder.34/contents
But still (3) always seems to come from cache. What am I doing wrong here?
HTTPBis is much clearer:
https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-p6-cache-22#section-6
Because unsafe request methods (Section 4.2.1 of [Part2]) such as
PUT, POST or DELETE have the potential for changing state on the
origin server, intervening caches can use them to keep their contents
up-to-date.
A cache MUST invalidate the effective Request URI (Section 5.5 of
[Part1]) as well as the URI(s) in the Location and Content-Location
response header fields (if present) when a non-error response to a
request with an unsafe method is received.
So if this is not the behavior you're seeing, my assumption would simply be that the particular HTTP client you are using does not have the correct behavior.
I'd especially expect:
Location: /folders/folder.34/contents
To have the correct behavior.

MVC website deployment issue

I've deployed MVC application to IIS 7.5 (Windows Server 2008 R2) successfully after some trouble with ASP.NET and dependencies and connections to database. I used import application feature of "Default Web Site".
This is my first time setting up IIS, so please bear with me.
It is set up at localhost/System. Now, I see that routing works because localhost/System (only /) gives my welcome view, and clicking login (localhost/System/Account/Login - /Accounts/Login) prompts me with login view.
Login populates menu from database, and all menu items are in this format: /Controller/Action/Values. When I click item in a menu, IIS issues a request localhost/Controller/Action - WITHOUT System. When I manually add system in the middle of request, naturally it works.
How am I to solve this?
I can easily change menu in database to add a /System prefix, but i have tons of same hard-coded addresses in java script all around the site. That would also mean that I am hard-coding the name of the site prior to deployment, and I don't like that.
Also, my site is completely white, as if IIS can't read my site.css file. It is located under /Content folder, and my site reference it like this:
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
What are your suggestions, how sould i solve this?
UPDATE:
I've been looking though IIS logs, and here are few lines:
GET /SYSTEM/Scripts/LookupJunction.js - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 200 0 0 31
GET /SYSTEM/Content/Site.css - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 200 0 0 31
GET /SYSTEM/Scripts/modernizr-1.7.min.js - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 200 0 0 31
GET /SYSTEM/Content/2012.1.214/telerik.Office2007.min.css - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 200 0 0 31
GET /SYSTEM/Content/2012.1.214/telerik.common.min.css - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 200 0 0 46
GET /SYSTEM/Scripts/jquery-1.5.1.min.js - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 200 0 0 46
GET /SYSTEM/Scripts/2012.1.214/telerik.common.min.js - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 200 0 0 15
GET /SYSTEM/Scripts/2012.1.214/telerik.menu.min.js - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 200 0 0 15
GET /SYSTEM/Scripts/2012.1.214/jquery-1.7.1.min.js - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 200 0 0 31
GET /Content/drock028.jpg - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 404 0 2 0
GET /SYSTEM/Content/2012.1.214/Office2007/sprite.png - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 200 0 0 15
GET /Home/Test - 80 - ::1 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+rv:15.0)+Gecko/20100101+Firefox/15.0.1 404 0 2 78
So, site.css is being loaded, but not my background image, it's path is missing 'SYSTEM' folder. I referenced it like this in my site.css:
background-image: url('/Content/drock028.jpg');
So, most of things get good urls, but not my background picture, and not calls to controller actions from database urls.
But, what should I do? I can't use URL helpers in database, nor can I use it in java script (or can I)?
For the first issue (URLs in the database), I would say leave the values in the format /Controller/Action, but update your views to render the application-relative URL:
#Url.Content("~" + url)
(So if the url from the database is /Home/Index, the above will give #Url.Content("~/Home/Index"), which will render /System/Home/Index.)
For the second part, as Nick noted, it might help to look at the Network tab in Firebug to see which URL is actually being requested for the CSS file (and whether it's getting a 404/Not Found, or something else). Your code for the CSS path is correct, so it may be an issue with the IIS configuration.

Resources