Nginx умеет кэшировать запросы самостоятельно. Преимущества использования Nginx cache в его простоте по сравнению с Varnish .
Что кешировать?Суть серверного кеширования в том, чтобы не генерировать постоянно одни и те же скрипты (например, ленту постов Wordpress), что может иногда занимать целые секунды. Вместо этого, приложение генерирует страницу один раз, и результат сохраняется в память. Когда посетитель запросит ту же страницу второй раз, генерации уже не будет, а клиент получит сохраненную в памяти версию. Раз в какое-то время (называемое ttl), эта сохраненная версия будет удаляться и генерироваться новая, чтобы поддерживать актуальность данных.
Почти на всех сайтах можно кэшировать страницы для неавторизованных пользователей. Хорошо подойдет для сайтов с контентом, который доступен публично.
Включение кеширования в NginxПрежде всего нужно определить максимальный размер кеша (общий размер всех страниц в кеше будет не более этого размера). Это делается в основном файле настроек (nginx.conf) в секции http:
Http { ... proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=all:32m max_size=1g ; ... }
# Устанавливаем размер кеша в 1G, сохранять его будем в папку /var/cache/nginx
Не забываем создать папку для кеша. mkdir /var/cache/nginx
Настройка хостовЧтобы кеширование заработало, мы должны создать новый хост, который будет слушать 80 порт. А основной хост перенести на какой-то другой порт (например, 81). Кеширующий хост будет посылать запросы на основной либо отдавать данные из кеша.
Кеширующий хост server { listen 80; location / { proxy_pass http://127.0.0.1:81/; proxy_cache all; proxy_cache_valid any 1h; } }# Каждая страница будет сохраняться в кеш на 1 час
Основной хост server { listen 81; location / { # fpm и т.п. } }# Обычный конфиг только на 81 порту
Cookies и персонализацияМногие сайты используют различные персональные блоки на страницах. Технология SSI позволяет реализовать продвинутое кеширование в случаях большого количество персонализированных блоков. В простом случае, мы можем просто отключать кеш, если у пользователя установлены какие-то Cookies.
Server { listen 80; location / { if ($http_cookie ~* ".+") { set $do_not_cache 1; } proxy_cache_bypass $do_not_cache; proxy_pass http://127.0.0.1:81/; proxy_cache all; proxy_cache_valid any 1h; } }
ОшибкиИмеет смысл также включить кеширование ошибочных запросов на какое-то короткое время. Это позволит избежать частых повторных попыток обратиться к неработающей части сайта.
Server { listen 80; location / { if ($http_cookie ~* ".+") { set $do_not_cache 1; } proxy_cache_bypass $do_not_cache; proxy_pass http://127.0.0.1:81/; proxy_cache all; proxy_cache_valid 404 502 503 1m; proxy_cache_valid any 1h; } }
Кеширование fastcgiNginx позволяет кешировать ответы от fastcgi. Для включения этого кеша, необходимо также объявить его параметры (в секции http файла nginx.conf):
Fastcgi_cache_path /var/cache/fpm levels=1:2 keys_zone=fcgi:32m max_size=1g; fastcgi_cache_key "$scheme$request_method$host$request_uri";
# Установим максимальный размер кеша в 1G
Не забываем создать папку mkdir /var/cache/fpm
В конфигурации основного хоста, добавляем правила кеширования:
Server { listen 80; location ~ \.php$ { fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_cache fcgi; fastcgi_cache_valid 200 60m; } }
# В данном случае мы будем кешировать ответы с кодом 200 на 60 минут
Самое важноеПользуйтесь преимуществами кеширования. Довольно просто в настройке, зато может дать десятикратное ускорение сайта и экономию ресурсов.
We all know that the performance of applications and web sites is a critical factor in their success. The process of making your application or web site perform better, however, is not always clear. Code quality and infrastructure are of course critical, but in many cases you can make vast improvements to the end user experience of your application by focusing on some very basic application delivery techniques. One such example is by implementing and optimizing caching in your application stack. This blog post covers techniques that can help both novice and advanced users see better performance from utilizing the included in NGINX and NGINX Plus.
OverviewA content cache sits in between a client and an “origin server”, and saves copies of all the content it sees. If a client requests content that the cache has stored, it returns the content directly without contacting the origin server. This improves performance as the content cache is closer to the client, and more efficiently uses the application servers because they don’t have to do the work of generating pages from scratch each time.
There are potentially multiple caches between the web browser and the application server: the client’s browser cache, intermediary caches, content delivery networks (CDNs), and the load balancer or reverse proxy sitting in front of the application servers. Caching, even at the reverse proxy/load balancer level, can greatly improve performance.
As an example, last year I took on the task of performance tuning a website that was loading slowly. One of the first things I noticed was that it took over 1 second to generate the main home page. After some debugging, I discovered that because the page was marked as not cacheable, it was being dynamically generated in response to each request. The page itself was not changing very often and was not personalized, so this was not necessary. As an experiment, I marked the homepage to be cached for 5 seconds by the load balancer, and just doing that resulted in noticeable improvement. The time to first byte went down to a few milliseconds and the page loaded visibly faster.
NGINX is commonly deployed as a reverse proxy or load balancer in an application stack and has a full set of caching features. The next section discusses how to configure basic caching with NGINX.
How to Set Up and Configure Basic CachingOnly two directives are needed to enable basic caching: proxy_cache_path and proxy_cache . The proxy_cache_path directive sets the path and configuration of the cache, and the proxy_cache directive activates it.
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_pass http://my_upstream; } }The parameters to the proxy_cache_path directive define the following settings:
And finally, the proxy_cache directive activates caching of all content that matches the URL of the parent location block (in the example, / ). You can also include the proxy_cache directive in a server block; it applies to all location blocks for the server that don’t have their own proxy_cache directive.
Delivering Cached Content When the Origin is Down location / { # ... proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504; }With this sample configuration, if NGINX receives an error , timeout , or any of the specified 5xx errors from the origin server and it has a stale version of the requested file in its cache, it delivers the stale file instead of relaying the error to the client.
Fine‑Tuning the Cache and Improving PerformanceNGINX has a wealth of optional settings for fine‑tuning the performance of the cache. Here is an example that activates a few of them:
Proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_cache_revalidate on; proxy_cache_min_uses 3; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_background_update on; proxy_cache_lock on; proxy_pass http://my_upstream; } }
These directives configure the following behavior:
If you have multiple hard drives, NGINX can be used to split the cache across them. Here is an example that splits clients evenly across two hard drives based on the request URI:
Proxy_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m max_size=10g inactive=60m use_temp_path=off; proxy_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m max_size=10g inactive=60m use_temp_path=off; split_clients $request_uri $my_cache { 50% “my_cache_hdd1”; 50% “my_cache_hdd2”; } server { # ... location / { proxy_cache $my_cache; proxy_pass http://my_upstream; } }
The two proxy_cache_path directives define two caches (my_cache_hdd1 and my_cache_hdd2) on two different hard drives. The split_clients configuration block specifies that the results from half the requests (50%) are cached in my_cache_hdd1 and the other half in my_cache_hdd2 . The hash based on the $request_uri variable (the request URI) determines which cache is used for each request, the result being that requests for a given URI are always cached in the same cache.
Please note this approach is not a replacement for a RAID hard drive setup. If there is a hard drive failure this could lead to unpredictable behavior on the system, including users seeing 500 response codes for requests that were directed to the failed hard drive. A proper RAID hard drive setup can handle hard drive failures.
Frequently Asked Questions (FAQ)This section answers some frequently asked questions about NGINX content caching.
Can the NGINX Cache Be Instrumented? add_header X-Cache-Status $upstream_cache_status;This example adds an X-Cache-Status HTTP header in responses to clients. The following are the possible values for $upstream_cache_status :
How Does NGINX Determine Whether or Not to Cache Something?By default, NGINX respects the Cache-Control headers from origin servers. It does not cache responses with Cache-Control set to Private , No-Cache , or No-Store or with Set-Cookie in the response header. NGINX only caches GET and HEAD client requests. You can override these defaults as described in the answers below.
proxy_cache_methods GET HEAD POST;This example enables caching of POST requests.
Can NGINX Cache Dynamic Content?Yes, provided the Cache-Control header allows for it. Caching dynamic content for even a short period of time can reduce load on origin servers and databases, which improves time to first byte, as the page does not have to be regenerated for each request.
Can I Punch a Hole Through My Cache? location / { proxy_cache_bypass $cookie_nocache $arg_nocache; # ... }The directive defines request types for which NGINX requests content from the origin server immediately instead of trying to find it in the cache first. This is sometimes referred to as “punching a hole” through the cache. In this example, NGINX does it for requests with a nocache cookie or argument, for example http://www.example.com/?nocache=true . NGINX can still cache the resulting response for future requests that aren’t bypassed.
What Cache Key Does NGINX Use?The default form of the keys that NGINX generates is similar to an MD5 hash of the following NGINX variables : $scheme$proxy_host$request_uri ; the actual algorithm used is slightly more complicated.
Proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { # ... location / { proxy_cache my_cache; proxy_pass http://my_upstream; } }
For this sample configuration, the cache key for http://www.example.org/my_image.jpg is calculated as md5(“http://my_upstream:80/my_image.jpg”) .
To change the variables (or other terms) used as the basis for the key, use the proxy_cache_key directive (see also the following question).
Can I Use a Cookie as Part of My Cache Key?Yes, the cache key can be configured to be any arbitrary value, for example:
proxy_cache_key $proxy_host$request_uri$cookie_jessionid;This example incorporates the value of the JSESSIONID cookie into the cache key. Items with the same URI but different JSESSIONID values are cached separately as unique items.
Does NGINX Use the ETag Header? How Does NGINX Handle the Pragma Header?The Pragma:no-cache header is added by clients to bypass all intermediary caches and go straight to the origin server for the requested content. NGINX does not honor the Pragma header by default, but you can configure the feature with the following proxy_cache_bypass directive:
Location /images/ { proxy_cache my_cache; proxy_cache_bypass $http_pragma; # ... }
Does NGINX Support the stale-while-revalidate and stale-if-error Extensions to the Cache-Control Header? Does NGINX Support the Vary Header? Further ReadingThere are many more ways you can customize and tune NGINX caching. To learn even more about caching with NGINX, please take a look at the following resources:
Кэширование данных на стороне клиента - возможность настроить разовую загрузку данных определенного типа с последующим их сохранением в памяти клиента. Кэширование браузера nginx или средствами другого сервера позволяет сократить количество обращений со стороны клиентской машины, и, как следствие, нагрузку, а также увеличить скорость загрузки сайтов.
Т.е. клиент обращается к странице сайта — сервер обрабатывает запрос, сгенерированная страница отправляется клиенту вместе с определенным заголовком. Браузер сохраняет информацию локально и при повторном запросе самостоятельно отдает ее.
Кэшируются изображения стили CSS и Javascript. Кэширование браузера Nginx реализуется за счет добавления заголовка Cache-control .
В заголовках служебная информация передается от сервера браузеру клиента, из нее браузер узнает когда нужно сохранять данные определенного типа и как долго удерживать их в памяти.
Кэширование браузера NginxВ конфигурационном файле Nginx кэширование JS/CSS включается следующим образом (добавлены и другие расширения — на практике лучше кэшировать их все):
server {
…
location ~* \.(jpg|jpeg|gif|png|ico|css|bmp|swf|js|html|txt)$ {
expires max;
root /home/website/example.com/;
}
…
}
expires max говорит о том, что TTL устанавливается в бесконечность и в случае если файлы на сервере будут изменены клиент об этом никогда не узнает поскольку повторный запрос отправлен не будет.
expires (об этом заголовке речь пойдет ниже) определяет когда брузер обновит кэш, значение устанавливается в секундах.
Обычно в конфиге сервера устанавливается именно значение expires max, затем в приложении при подключении css и js файлов определяются их версии, которые должны меняться каждый раз при обновлении содержимого.
Указание заголовков, задающих кэширование на уровне приложения
Сервер в этом случае будет воспринимать каждую новую версию как добавленный новый файл и будет кэшировать его.
Вместе с Cache-Control часто указывается заголовок Expires — он принудительно задает дату и время, когда браузер сбросит существующий кэш; при следующем обращении к пользователя обновленные данные будут загружены в кэш повторно.
Дополнительный заголовок HTTP Expires указывает дату и время, когда браузер должен обновить кэш (заголовки можно использовать совместно, Expires при использовании обоих заголовков имеет меньшее значение):
Оба заголовка могут быть заданы в программном коде на уровне приложения.
Включение кэширования в РНРБольшая часть веб-проектов пишутся на языке РНР, в РНР HTTP заголовки Cache-control и Expires задаются следующим образом: