Imagine that we have a website that regularly provides links from Habr.
We need to prepare it for sharp spikes in attendance. How to do it?
Since version 0.8.46, options have been added to nginx that allow you to easily and easily configure transparent caching for anonymous users.
Very little is required from the site for this scheme to work: it’s enough just not to start a session, that is, not to send a session cookie, unless necessary. A rare site cannot be brought to such a state, which means that most sites can be protected from sudden surges in attendance with the help of nginx with minimal effort and time.
')
We teach the site to start a session only when it is needed.
For widely used sites in PHP, this can be done by setting the session.auto_start in php.ini to zero or, better, in the Apache virtual host settings. We also need to set a suitable name for the session cookie:
php_admin_value session.name "session" php_admin_value session.auto_start 0
If the site itself starts the session in the code, then
session_start () should be replaced by:
if (!empty($_COOKIE[session_name()]) || $_SERVER['REQUEST_METHOD'] == 'POST') { session_id() || session_start(); }
So, the session will be started only if
- Session cookie already exists or if
- we are sent a form, for example, with a login and password.
What we needed.
Configure nginx to cache requests without session cookies.
After we have ensured that the site does not send a session cookie to the site guests, we configure nginx to save to the cache requests without a session cookie.
In any convenient place, for example, in the nginx virtual host config before the server block, add the lines:
proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=cache:30m max_size=1G; proxy_temp_path /var/lib/nginx/proxy 1 2; proxy_ignore_headers Expires Cache-Control; proxy_cache_use_stale error timeout invalid_header http_502; proxy_cache_bypass $cookie_session; proxy_no_cache $cookie_session;
Do not forget to create the appropriate directories:
mkdir -p /var/lib/nginx/cache chown -R www-data /var/lib/nginx/cache chmod 700 /var/lib/nginx/cache
In the appropriate location block, add the highlighted three lines:
location / { .... proxy_cache cache; proxy_cache_valid 10m; proxy_cache_valid 404 1m; .... proxy_pass http:
Restart nginx, delete cookies from the browser and enjoy the speed of the site.
Tweaking caching
If you want only some pages to be cached, or, for example, that some addresses are cached for more than 10 minutes, to explicitly set the caching time, use:
header("X-Accel-Expires: $seconds");
To completely disable caching, for example, counters, use:
header("X-Accel-Expires: 0");
Test of strength
Check the main page of the site for strength in one hundred threads:
ab -n 1000 -c 100 http://www.example.com/
With the use of caching, the test site easily gave out more than 100 rps, which is understandable.
Without cache - predictably showed 503 errors for ~ 70% of requests.
Forced cache refresh
If in the directive proxy_cache_bypass change as follows:
proxy_cache_bypass $cookie_session $http_x_update;
It will be possible to forcibly update the page cache if necessary:
curl -s -o /dev/null -H "X-Update: 1" www.example.com
The heading is better to replace with any other, known only to you.