Nginx кэширование на стороне клиента. Кэширование с Nginx. Активация кэширования FastCGI

В web-сервер и reverse-proxy nginx встроены очень мощные возможности по кэшированию HTTP-ответов. Однако в ряде случаев документации и примеров не хватает, в результате не все получается так легко и просто, как хотелось бы. Например, мои конфиги nginx-а местами написаны кровью. Этой статьей я попробую немного улучшить ситуацию.

В этой статье: а) подводные камни при полностраничном кэшировании; б) кэширование с ротацией; в) создание динамического «окна» в закэшированной странице.

Я буду предполагать, что вы используете связку nginx+fastcgi_php. Если вы применяете nginx+apache+mod_php, просто замените имена директив с fastcgi_cache* на proxy_cache*

Если выбирать, кэшировать ли страницу на стороне PHP или на стороне nginx, я выбираю nginx. Во-первых, это позволяет отдавать 5-10 тыс. запросов в секунду без каких-либо сложностей и без умных разговоров о «высокой нагрузке». Во-вторых, nginx самостоятельно следит за размером кэша и чистит его как при устаревании, так и при вытеснении нечасто используемых данных.

Кэширование всей страницы целиком

Если на вашем сайте главная страница хоть и генерируется динамически, но меняется достаточно редко, можно сильно снизить нагрузку на сервер, закэшировав ее в nginx. При высокой посещаемости даже кэширование на короткий срок (5 минут и меньше) уже дает огромный прирост в производительности, ведь кэш работает очень быстро. Даже закэшировав страницу всего на 30 секунд, вы все равно добьетесь значительной разгрузки сервера, сохранив при этом динамичность обновления данных (во многих случаях обновления раз в 30 секунд вполне достаточно).

Например, закэшировать главную страницу можно так:

Fastcgi_cache_path /var/cache/nginx levels= keys_zone=wholepage:50m; ... server { ... location / { ... fastcgi_pass 127.0.0.1:9000; ... # Включаем кэширование и тщательно выбираем ключ кэша. fastcgi_cache wholepage; fastcgi_cache_valid 200 301 302 304 5m; fastcgi_cache_key "$request_method|$http_if_modified_since|$http_if_none_match|$host|$request_uri"; # Гарантируем, что разные пользователи не получат одну и ту же сессионную Cookie. fastcgi_hide_header "Set-Cookie"; # Заставляем nginx кэшировать страницу в любом случае, независимо от # заголовков кэширования, выставляемых в PHP. fastcgi_ignore_headers "Cache-Control" "Expires"; } }

Я не сильно преувеличу, если скажу, что каждая строчка в этом конфиге написана кровью. Здесь много подводных камней, давайте их все рассмотрим.

fastcgi_cache_path: простота отладки тоже важна

fastcgi_cache_path /var/cache/nginx levels= keys_zone=wholepage:50m;

В директиве fastcgi_cache_path я выставляю «пустое» значение для levels. Хотя это немного снижает производительность (файлы будут напрямую создаваться в /var/cache/nginx, без разбиения по директориям), но зато на порядок облегчает отладку и диагностику проблем с кэшем. Поверьте, вам еще не раз придется руками залезать в /var/cache/nginx и смотреть, что там хранится.

fastcgi_cache_valid: кэшируем код ответа 304 тоже

fastcgi_cache_valid 200 301 302 304 5m;

В директиве fastcgi_cache_valid мы заставляем кэшировать не только стандартные коды 200 ОК, 301 Moved Permanently и 302 Found, но также и 304 Not Modified. Почему? Давайте вспомним, что означает 304. Он выдается с пустым телом ответа в двух случаях:

  • Если браузер послал заголовок «If-Modified-Since: date», в котором date больше либо равна значению заголовка ответа «Last-Modified: date». Т.е. клиент спрашивает: «Есть ли новая версия с момента date? Если нет, верни мне 304 и сэкономь трафик. Если есть, отдай мне тело страницы».
  • Если браузер послал заголовок «If-None-Match: hash», где hash совапдает со значением заголовка ответа «ETag: hash». Т.е. клиент спрашивает: «Отличается ли текущая версия страницы от той, что я запросил в прошлый раз? Если нет, верни мне 304 и сэкономь трафик. Если да, отдай тело страницы».

В обоих случаях Last-Modified или ETag будут взяты, скорее всего, из кэша nginx, и проверка пройдет очень быстро. Нам незачем «дергать» PHP только для того, чтобы скрипт выдал эти заголовки, особенно в свете того, что клиентам, которым уйдет ответ 200, он будет отдан из кэша.

fastcgi_cache_key: внимательно работаем с зависимостями

fastcgi_cache_key «$request_method|$http_if_modified_since|$http_if_none_match|$host|$request_uri»;

Особого внимания заслуживает значение в директиве fastcgi_cache_key. Я привел минимальное рабочее значение этой директивы. Шаг вправо, шаг влево, и вы начнете в ряде случаев получать «неправильные» данные из кэша. Итак:

  • Зависимость от $request_method нам нужна, т.к. HEAD-запросы в Интернете довольно часты. Ответ на HEAD-запрос никогда не содержит тела. Если убрать зависимость от $request_method, то может так совпасть, что кто-то до вас запросил главную страницу HEAD-методом, а вам потом по GET отдастся пустой контент.
  • Зависимость от $http_if_modified_since нужна для того, чтобы кэш с ответом 304 Not Modified не был случайно отдан клиенту, делающему обычный GET-запрос. Иначе клиент может получить пустой ответ из кэша.
  • То же самое и с $http_if_none_match. Мы должны быть застрахованы от выдачи пустых страниц клиентам!
  • Наконец, зависимость от $host и $request_uri не требует комментариев.
fastcgi_hide_header: решаем проблемы с безопасностью

fastcgi_hide_header «Set-Cookie»;

Директива fastcgi_hide_header очень важна. Без нее вы серьезно рискуете безопасностью: пользователи могут получить чужие сессии через сессионную Cookie в кэше. (Правда, в последних версиях nginx что-то было сделано в сторону автоматического учета данного фактора.) Понимаете, как это происходит? На сайт зашел Вася Пупкин, ему выдалась сессия и сессионная Cookie. Пусть кэш на тот момент оказался пустым, и в него записалась Васина Cookie. Затем пришел другой пользователь, получил ответ из кэша, а в нем - и Cookie Васи. А значит, и его сессию тоже.

Можно, конечно, сказать: давайте не будем вызывать session_start () на главной странице, тогда и с Cookies проблем не будет. В теории это так, но на практике данный способ очень неустойчив. Сессии часто стартуют «отложено», и достаточно какой-либо части кода «случайно» вызвать функцию, требующую доступа к сессии, как мы получим дыру в безопасности. А безопасность - такая штука, что если в той или иной методике может возникнуть дыра по неосторожности, то эта методика считается «дырявой» по определению. К тому же есть и другие Cookies, кроме сессионной; их тоже не надо записывать в кэш.

fastcgi_ignore_headers: не даем сайту «лечь» от нагрузки при опечатке

fastcgi_ignore_headers «Cache-Control» «Expires»;

Сервер nginx обращает внимание на заголовки Cache-Control, Expires и Pragma, которые выдает PHP. Если в них сказано, что страницу не нужно кэшировать (либо что она уже устарела), то nginx не записывает ее в кэш-файл. Это поведение, хотя и кажется логичным, на практике порождает массу сложностей. Поэтому мы его блокируем: благодаря fastcgi_ignore_headers в кэш-файлы попадет содержимое любой страницы, независимо от ее заголовков.

Что же это за сложности? Они опять связаны с сессиями и функцией session_start (), которая в PHP по умолчанию выставляет заголовки «Cache-Control: no-cache» и «Pragma: no-cache». Здесь существует три решения проблемы:

  • Не пользоваться session_start () на странице, где предполагается кэширование. Один из минусов этого способа мы уже рассмотрели выше: достаточно одного неосторожного движения, и ваш сайт, принимающий тысячи запросов в секунду на закэшированную главную страницу, моментально «ляжет», когда кэш отключится. Второй минус - нам придется управлять логикой кэширования в двух местах: в конфиге nginx и в PHP-коде. Т.е. эта логика окажется «размазанной» по совершенно разным частям системы.
  • Выставить ini_set ("session.cache_limiter", ""). Это заставит PHP запретить вывод каких-либо заголовков, ограничивающих кэширование при работе с сессиями. Проблема здесь та же: «размазанность» логики кэширования, ведь в идеале мы бы хотели, чтобы все кэширование управлялось из единого места.
  • Игнорировать заголовки запрета кэширования при записи в кэш-файлы при помощи fastcgi_ignore_headers. Кажется, это беспроигрышное решение, поэтому я его и советую.

Кэширование с ротацией

Статическая главная страница - это не так уж и интересно. Что делать, если на сайте много материалов, а Главная выступает в роли своеобразной «витрины» для них? На такой «витрине» удобно отображать «случайные» материалы, чтобы разные пользователи видели разное (и даже один пользователь получал новый контент, перезагрузив страницу в браузере).

Решение задачи - кэширование с ротацией:

  1. Мы заставляем скрипт честно выдавать элементы главной странице в случайном порядке, выполняя необходимые запросы в базу данных (пусть это и медленно).
  2. Затем мы сохраняем в кэше не одну, а, скажем, 10 вариантов страницы.
  3. Когда пользователь заходит на сайт, мы показываем ему один из этих вариантов. При этом, если кэш пуст, то запускается скрипт, а если нет, то результат возвращается из кэша.
  4. Устанавливаем время устаревания кэша малым (например, 1 минута), чтобы за день разные пользователи «отсмотрели» все материалы сайта.

В итоге первые 10 запросов к скрипту-генератору выполнятся «честно» и «нагрузят» сервер. Зато потом они «осядут» в кэше и в течение минуты будут выдаваться уже быстро. Прирост производительности тем больше, чем больше посетителей на сайте.

Вот кусочек конфига nginx, реализующий кэширование с ротацией:

Fastcgi_cache_path /var/cache/nginx levels= keys_zone=wholepage:50m; perl_set $rand "sub { return int rand 10 }"; ... server { ... location / { ... fastcgi_pass 127.0.0.1:9000; ... # Включаем кэширование и тщательно выбираем ключ кэша. fastcgi_cache wholepage; fastcgi_cache_valid 200 301 302 304 1m; fastcgi_cache_key "$rand|$request_method|$http_if_modified_since|$http_if_none_match|$host|$request_uri"; # Гарантируем, что разные пользователи не получат одну и ту же сессионную Cookie. fastcgi_hide_header "Set-Cookie"; # Заставляем nginx кэшировать страницу в любом случае, независимо от # заголовков кэширования, выставляемых в PHP. fastcgi_ignore_headers "Cache-Control" "Expires"; # Заставляем браузер каждый раз перезагружать страницу (для ротации). fastcgi_hide_header "Cache-Control"; add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"; fastcgi_hide_header "Pragma"; add_header Pragma "no-cache"; # Выдаем всегда свежий Last-Modified. expires -1; # Внимание!!! Эта строка expires необходима! add_header Last-Modified $sent_http_Expires; } }

Вы можете заметить, что по сравнению с предыдущим примером мне пришлось добавить еще 6 директив в location. Они все очень важные! Но не будем забегать вперед, рассмотрим все по порядку.

perl_set: зависимость-рандомизатор

perl_set $rand "sub { return int rand 10 }";

С директивой perl_set все просто. Мы создаем переменную, при использовании которой nginx будет вызывать функцию встроенного в него Perl-интерпретатора. По словам автора nginx, это достаточно быстрая операция, так что мы не будем «экономить на спичках». Переменная принимает случайное значение от 0 до 9 в каждом из HTTP-запросов.

fastcgi_cache_key: зависимость от рандомизатора

fastcgi_cache_key «$rand|$request_method|...»;

Теперь мы замешиваем переменную-рандомизатор в ключ кэша. В итоге получается 10 разных кэшей на один и тот же URL, что нам и требовалось. Благодаря тому, что скрипт, вызываемый при кэш-промахе, выдает элементы главной страницы в случайном порядке, мы получаем 10 разновидностей главной страницы, каждая из которой «живет» 1 минуту (см. fastcgi_cache_valid).

add_header: принудительно выключаем браузерный кэш
fastcgi_hide_header "Cache-Control"; add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"; fastcgi_hide_header "Pragma"; add_header Pragma "no-cache";

Выше мы говорили, что nginx чувствителен к кэш-заголовкам, выдаваемым PHP-скриптом. Если PHP-скрипт возвращает заголовки «Pragma: no-cache» или «Cache-Control: no-store» (а также еще некоторые, например, «Cache-Control: не-сохранять, не-выдавать, меня-тут-не-было, я-этого-не-говорил, чья-это-шляпа»), то nginx не будет сохранять результат в кэш-файлах. Специально чтобы подавить такое его поведение, мы используем fastcgi_ignore_headers (см. выше).

Чем отличается «Pragma: no-cache» от «Cache-Control: no-cache»? Только тем, что Pragma - наследие HTTP/1.0 и сейчас поддерживается для совместимости со старыми браузерами. В HTTP/1.1 используется Cache-Control.

Однако есть еще кэш в браузере. И в некоторых случаях браузер может даже не пытаться делать запрос на сервер, чтобы отобразить страницу; вместо этого он достанет ее из собственного кэша. Т.к. у нас ротация, нам такое поведение неудобно: ведь каждый раз, заходя на страницу, пользователь должен видеть новые данные. (На самом деле, если вы все же хотите закэшировать какой-нибудь один вариант, то можно поэкспериментировать с заголовком Cache-Control.)

Директива add_header как раз и передает в браузер заголовок запрета кэширования. Ну а чтобы этот заголовок случайно не размножился, мы вначале убираем из HTTP-ответа то, что записал туда PHP-скрипт (и то, что записалось в nginx-кэш): директива fastcgi_hide_header. Ведь вы, когда пишете конфиг nginx-а, не знаете, что там надумает выводить PHP (а если используется session_start (), то он точно надумает). Вдруг он выставит свой собственный заголовок Cache-Control? Тогда их будет два: PHP-шный и добавленный нами через add_header.

expires и Last-Modified: гарантируем перезагрузку страницы
expires -1; # Внимание!!! Эта строка expires необходима! add_header Last-Modified $sent_http_Expires;

Еще один трюк: мы должны выставить Last-Modified равным текущему времени. К сожалению, в nginx нет переменной, хранящей текущее время, однако она магическим образом появляется, если указать директиву expires -1.

Хотя это сейчас (октябрь 2009 г.) не задокументировано, nginx создает переменные вида $sent_http_XXX для каждого заголовка ответа XXX, отданного клиенту. Одной из них мы и пользуемся.

Почему же так важно выставлять текущим временем этот заголовок? Все довольно просто.

  1. Давайте представим, что PHP выдал заголовок «Last-Modified: некоторая_дата».
  2. Данный заголовок будет записан в кэш-файл nginx (можете проверить: в нашем примере файлы хранятся в /var/cache/nginx), а потом отдан в браузер клиенту.
  3. Браузер запомнит страницу и дату ее модификации...
  4. … поэтому при следующем заходе пользователя на сайт в HTTP-запросе будет заголовок-вопрос «If-Modified-Since: некоторая_дата».
  5. Что же сделает nginx? Он достанет страницу из своего кэша, разберет ее заголовки и сравнит Last-Modified с If-Modified-Since. Если значения совпадут (или первое окажется меньше второго), то nginx вернет ответ «304 Not Modified» с пустым телом. И пользователь не увидит никакой ротации: он получит то, что уже видел раньше.

На самом деле, большой вопрос, как поведет себя браузер при наличии одновременно Last-Modified и Cache-Control no-cache. Будет ли он делать запрос If-Modified-Since? Кажется, что разные браузеры ведут тут себя по-разному. Экспериментируйте.

Есть и еще один повод выставлять Last-Modified вручную. Дело в том, что PHP-функция session_start () принудительно выдает заголовок Last-Modified, но указывает в нем… время изменения PHP-файла, который первый получил управление. Следовательно, если у вас на сайте все запросы идут на один и тот же скрипт (Front Controller), то ваша Last-Modified будет почти всегда равна времени изменения этого единственного скрипта, что совершенно не верно.

Динамическое «окно» в закэшированной странице

Ну и напоследок упомяну одну технику, которая может быть полезна в свете кэширования. Если вам хочется закэшировать главную (или любую другую) страницу сайта, однако мешает один маленький блок, который обязательно должен быть динамическим, воспользуйтесь модулем для работы с SSI.

В ту часть страницы, которая должна быть динамической, вставьте вот такой «HTML-комментарий»:

С точки зрения кэша nginx данный комментарий - обычный текст. Он будет сохранен в кэш-файле именно в виде комментария. Однако позже, при прочтения кэша, сработает модуль SSI nginx, который обратится к динамическому URL. Конечно, по адресу /get_user_info/ должен быть PHP-обработчик, который выдает содержимое данного блока.

Ну и, естественно, не забудьте включить SSI для этой страницы или даже для всего сервера:

Директива SSI include имеет еще одно, крайне важное свойство. Когда на странице встречаются несколько таких директив, то все они начинают обрабатываться одновременно, в параллельном режиме. Так что, если у вас на странице 4 блока, каждый из которых загружается 200мс, в сумме страница будет получена пользователем через 200мс, а не через 800.

Nginx часто применяется в веб-проектах не в малой степени потому, что позволяет временно сохранять контент сайтов. В Nginx кэширование настраивается очень просто (по сравнению с другими хранилищами) и является хорошим средством оптимизации работы веб-сервера.

Используется при больших нагрузках. Кэширование позволяет быстрее отдавать контент при втором и последующих обращениях к сайту. В блоге Nginx про кэширование .

Также кэширующие сервера легко кластеризуются

Чтобы кэширование nginx работало корректно в конфигурационном файле nginx.conf определяется путь к каталогу, в который будут складываться закэшированные на стороне сервера данные и задается его размер.

Рассматривается серверное кэширование и использование Nginx как хранилища. задается проще.

Запускается веб-сервер в двух экземплярах на разных портах, обычно на разных машинах.

Кэширующий веб-сервер дает снижение нагрузки. Страница, один раз сгенерированная, сохраняется в кэш и отдается клиентам из него пока не истечет установленный TTL (time to live). Когда он истечет страница вновь будет сгенерирована и загружена в кэш — это требуется для того, чтобы посетитель сайта получал актуальную информацию.

Nginx кэширование: настройка

В примере закэшированные данные будут складываться на сервере 123.123.123.123 в каталог /var/cache/nginx . Максимальный размер файлов в кэше — 128 Мб, если этого буфера будет не хватать самые редко запрашиваемые данные будут вытесняться

mcedit /etc/nginx/nginx.conf

http {
proxy_cache_path /var/nginx/cache levels=1:2 keys_zone=all:128m;
}

Каталог /var/nginx/cache нужно создать

mkdir -p /var/nginx/cache

Настройка виртуального хоста

Все, что здесь требуется — принимать запросы на выбранном для кэширующего Nginx, затем проксировать их на основной сервер.

server {
listen *:80;

server_name example.com;
access_log /var/log/nginx/access.log;

location / {

proxy_pass http://124.124.124.124:80/;
proxy_set_header Host $host;
proxy_buffering on;
proxy_cache all;
proxy_cache_valid any 30m;
proxy_cache_valid 200 1d;
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;

}

В конфигурационном файле указано, что кэшировать нужно все содержимое, TTL установлен в 30 минут.

Виртуальный хост активируется

На основном Nginx сервере с адресом 124.124.124.124:

Никаких изменений здесь вносить не требуется — можно при необходимости запустить веб-сервер на альтернативном порту.

mcedit /etc/nginx/sites-availible/example.com

server {
listen *:80;
server_name example.com;
proxy_read_timeout 200s;
access_log off;

root /var/www/sites/example.com/;

location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

}

}

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled

Конфигурация может быть любой: Nginx + PHP-FPM или как в примере.

Добавляем файл index.php для того чтобы проверить кэширование

mcedit /var/www/sites/example.com/index.php

echo «Works!»;

?>

Теперь можно обратиться к сайту через браузер, «Works!» будет говорить о том, что запросы успешно перенаправляются.

На кэширующем Nginx сервере с адресом 123.123.123.123:

Теперь можно проверить появилось ли что-либо в каталоге, выделенном под хранилище данных

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; } }

Кеширование fastcgi

Nginx позволяет кешировать ответы от 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 минут

Самое важное

Пользуйтесь преимуществами кеширования. Довольно просто в настройке, зато может дать десятикратное ускорение сайта и экономию ресурсов.

Давно минули те старые добрые времена, когда сайты были сделаны на голом HTML и их страницы весили несколько десятков килобайт. А интернет был на dial-up.

Страницы современных сайтов весят уже несколько сотен килобайт, а частенько и несколько мегабайт. Картинки, скрипты, файлы стилей CSS - всё это непременные атрибуты нормального современного сайта и без них никак. А весит всё это «счастье» совсем не мало, и каждый раз посетители, зашедшие на ваш сайт, загружают всё это на свой компьютер. И пока загрузка не завершится, в браузере страница не откроется.

Рассмотрим метод борьбы с этой проблемой посредством вебсервера Nginx. Суть в том, что мы сделаем 2 вещи - сожмём все статические файлы (скрипты, файлы стилей) посредством gzip, и закэшируем их вместе с картинками в кэше браузера посетителя, чтобы они каждый раз не загружались с сайта, а брались прямо из кэша на компьютере посетителя сайта.

Настройка сжатия данных посредством Nginx.

Открываем файл конфигурации Nginx, расположенный по адресу /etc/nginx/nginx.conf

И в секцию http {…}, которая находится в начале файла добавляем то, чего там нет из примера ниже:

Gzip on; gzip_static on; gzip_comp_level 5; gzip_min_length 1024; gzip_proxied any; gzip_types text/plain application/xml application/x-javascript text/javascript text/css text/json;

Настройка кэширования статических файлов в кэше браузера пользователя, посредством Nginx.

В том же файле /etc/nginx/nginx.conf спускаемся ниже, находим конструкцию server для нужного сайта и дописываем туда:

Location ~* ^.+.(jpg|jpeg|gif|png|ico|css|pdf|ppt|txt|bmp|rtf|js)$ { root /var/www/user/data/www/site.ru; expires 7d;

где expires 7d - это количество дней, сколько кэш статических файлов должен храниться на компьютере пользователя. Если вы не вносите правки в css, js, файлы своего сайта и не меняете картинки, то имеет смысл этот параметр увеличить, вплоть до нескольких месяцев или даже до года.

Для наглядности приводим участок секции server из сервера, в котором Nginx был установлен стандартными средствами панели ISPmanager:

Server { server_name site.ru www.site.ru; listen 111.121.152.21; disable_symlinks if_not_owner from=$root_path; set $root_path /var/www/user/data/www/site.ru; location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf)$ { root $root_path; access_log /var/www/nginx-logs/user isp; access_log /var/www/httpd-logs/site.ru.access.log ; error_page 404 = @fallback; }

А теперь мы добавим сюда expires 7d , теперь это будет выглядеть вот так:

Server { server_name site.ru www.site.ru; listen 111.121.152.21; disable_symlinks if_not_owner from=$root_path; set $root_path /var/www/user/data/www/site.ru; location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf)$ { root $root_path; expires 7d; access_log /var/www/nginx-logs/user isp; access_log /var/www/httpd-logs/site.ru.access.log ; error_page 404 = @fallback; }

Перезагружаем Nginx командой:

Service nginx restart

Заходим на свой сайт и радуемся, он теперь стал загружаться в несколько раз быстрее. А вес страниц сайта снизился с нескольких мегабайт до пары десятков килобайт!

Данная статья будет полезна для владельцев виртуальных и выделенных серверов, так как у пользователей виртуального хостинга нет доступа к редактированию конфигурации Nginx. Однако клиенты виртуального хостинга , предлагаемого нашей организацией всегда могут обратиться в службу поддержки, и наши системные администраторы внесут необходимые настройки для вашего сайта.



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: