I am trying to use proxy_cache_use_stale error; to let the nginx serve a cached page when a target returns http status 500 internal error.
I have the following setup:
location /test {
proxy_cache maincache;
proxy_cache_valid 200 10s;
proxy_cache_use_stale error;
proxy_pass http://127.0.0.1:3000/test;
}
location /toggle {
proxy_pass http://127.0.0.1:3000/toggle;
}
Test will return either the current time and Http status 200 or the current time and http status 500. If i call /toggle the value returned from /test will switch from 200 to 500.
My expectation was that I should be able to send a call to /test and get the current time. I should then be able to send a call to /toggle and calls to /test would return the time when the function was first called. What is happening is that it keeps its last cache for 10 seconds and then sending back the current time and not using cache at all.
I understand that setting proxy_cache_valid 200 10s; will keep it from refreshing the cache when something other than 500 is returned and store new content in the cache when 10 seconds has passed and a none error message is
returned.
What i assumed after reading the documentation, old cache would not be automatically cleared until time passed equal to the inactive flag set for a cache. I have not set the inactive flag for cache so i expected the "proxy_cache_use_stale error" would prevent the cache from refreshing until either 10 minutes passed (default value when inactive is not defined), or errors are no longer returned. What part of the documentation have i misunderstood? How should this be done correctly?
Nginx documentation that i am refering to is the one found here.
http://nginx.org/en/docs/http/ngx_http_proxy_module.html?&_ga=1.112574977.446076600.1424025436#proxy_cache
you should use "http_500" instead of "error", see http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream (proxy_cache_use_stale uses same arguments as proxy_next_upstream)
Related
I want to redirect every http request to https. I have modified my VCL file as:
import std;
sub vcl_recv {
if (std.port(server.ip) != 443) {
set req.http.location = "https://" + req.http.host + req.url;
return(synth(301));
}
}
sub vcl_synth {
if (resp.status == 301 || resp.status == 302) {
set resp.http.location = req.http.location;
return (deliver);
}
}
It worked but it increases my site loading to approximately 1s, whether the request is http or https.
Is there any other alternative approach i can use or improve load time performance?
Varnish hardly adds latency to the request/response flow.
If the HTTPS resource that is redirected to is not cached, you will depend on the performance of your origin server. If the origin server is slow, the loading time will be slow.
Browser timing breakdown
Please analyse the breakdown of the loading time for that resource in the "network" tab of your browser's inspector.
For that page that is loaded, you can click the "Timings" tab in Firefox to see the breakdown. Here's an example:
If the Waiting timer is high, this means the server is slow.
If the Receiving timer is high, this means the network is slow.
Varnish timing breakdown
The varnishlog program allows you to inspect detailed transactions logs for Varnish.
The varnishlog -g request -i ReqUrl -i Timestamp will list the URL and loading times of every transaction.
Here's an example:
root#varnish:/etc/varnish# varnishlog -c -g request -i ReqUrl -i Timestamp
* << Request >> 163843
- Timestamp Start: 1645036124.028073 0.000000 0.000000
- Timestamp Req: 1645036124.028073 0.000000 0.000000
- ReqURL /
- Timestamp Fetch: 1645036124.035310 0.007237 0.007237
- Timestamp Process: 1645036124.035362 0.007288 0.000051
- Timestamp Resp: 1645036124.035483 0.007409 0.000120
Timestamps are expressed in UNIX timestamp format. The first timer in every Timestamp log line is the total loading time since the start of the transaction. The second one is the loading time of the individual part.
In this example the total server-side loading time was 0.007409 seconds. The backend fetch was responsible for 0.007237 seconds of loading time.
Varnish itself wasted 0.007237 seconds on processing before the fetch, 0.000051 seconds of processing after the fetch and 0.000120 seconds for sending the response.
You can use this command to inspect server-side performance at your end. It also allows you to inspect whether or not Varnish is to blame for any incurred latency.
When there's no Fetch line it means you're dealing with a cache hit and no backend fetch was required.
Conclusion
Combine server-side timing breakdown and client-side timing breakdown to form a conclusion on what causes the delay. Based on that information you can improve the component that is causing this delay.
It might help to add synthetic("") to your vcl_synth {} to make sure that the redirects are sent with an empty body, but I agree that the code should not increase the response time by any significant amount.
I have a RESTful web service written with Flask framework.
To make it simple, let's assume that all requests are GET, that is only request line + headers.
Request buffering time usually takes about 100ms, processing time - 1 second/request.
During stress tests I found an issue:
When lots of clients (hundreds+) open a connection to it at the same time, there's a delay between connections opened and start of processing.
It turned out that Flask reads a headers part of HTTP requests upon connection. More connections -> more headers to read -> bigger networking load -> bigger request buffering time.
For example: 100 simultaneously opened connections will start buffering together and will take 0.1*100=10 seconds to buffer. They will then pass to processing stage together.
My intention is to reach 2 goals:
Primary: Start processing as quick as possible
Secondary: Buffer all requests as quick as possible
Despite a seeming contradiction, both of them can be achieved by preserving a rule:
Buffering less connections, if there's a processing starvation.
Once again, to make it simple, I want my server to buffer only 10 connections at a time (/second). All the other connections should be accepted by server socket and wait patiently for their turn. Alternatively, accept only 10 connections/second (and still wait for others, not to discard bursts).
I tried to do it with NGINX reverse proxy with limit_req:
http {
limit_req_zone $server_name zone=processing_limit:10m rate=1r/s;
}
location ~ /process {
# Limit requests
limit_req zone=processing_limit burst=1000;
include proxy_params;
proxy_pass_header Server;
proxy_request_buffering on;
proxy_buffering off;
client_max_body_size 100m;
proxy_pass http://127.0.0.1:8081;
}
But NGINX also buffers all connections together and only forwards 1 request/sec to a backend server.
I'm new with JMeter and I'm working with a script for checking the cache, the scenario was to:
do a GET request
verify that it has been cached
do a DELETE request
verify that the cache has been deleted
However since there are three instances in the environment I'm working on my script is having intermittent failures because of the different x-internal-service-host being returned.
My test results looks like this:
do a GET request (x-internal-service-host returned is
c3c8021a51a9:8080 - PASS)
verify that it has been cached
(x-internal-service-host returned is 4eb7ac9d4a76:8080 - FAILED
because the call made was for c3c8021a51a9:8080)
do a DELETE
request (x-internal-service-host returned
is c3c8021a51a9:8080 - PASS)
verify that the cache has been deleted
(request x-internal-service-host returned is c3c8021a51a9:8080 -
FAILED because the delete was made for 4eb7ac9d4a76:8080)
I'm thinking of extracting the Response Header x-internal-service-host in step 1 but I'm not sure how to proceed once extracted, is it possible to send a GET request until the Response Header extracted matches the Response Header result for steps 2 to 4 or is there a better way to do this?
The dev team came to me and the Senior Sys Admin and stated that a 400 error is popping up when it needs to be a 404.
I ran an infinite loop to see the output with:
while :; do wget http://<URL here>/-`date +%s`; sleep 1; done
It just appends an incremented Unix timestamp since I know it should be a 404. The output shows 404 every 10-15 iterations, then shows a single 400, then repeats the cycle.
We have tried to edit the ErrorDocument directive to point to a custom 404 error document to no avail.
What could be causing this 400 error to pop up every few requests?
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.