|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Всё о кешировании сайта: nginx, memcached, expires, etag, плагины. Nginx кэш браузераКеширование сайта: nginx, memcached, expires, etagЧто такое кешированиеКеширование (caching) — это технология или процесс создания копии данных на быстродоступных носителях информации (кеш, cash). Проще говоря и применяя к реалиям сайтостроения, это может быть создание статической html-копии страницы или её части, которая генерируется с помощью PHP-скриптов (или иных других, как-то Perl, ASP.net), смотря на каком языке написан CMS сайта) и сохраняется на диске, в оперативной памяти или даже частично в браузере (рассмотрим подробнее ниже). Когда произойдёт запрос страницы от клиента (браузера), вместо того, чтобы заново собирать её скриптами, браузер получит её готовую копию, что намного экономнее по затратам ресурсов хостинга, и быстрее, так как передать готовую страницу занимает меньше времени (порой значительно меньше), чем её создание заново. Зачем использовать кеширование на сайте
Оба аргумента, думаю, в комментариях не нуждаются. Недостатки и отрицательный эффект от кеширования сайтаКак ни странно, у кеширования сайта есть и свои минусы. В первую очередь это касается сайтов, содержание которых динамично изменяется при взаимодействии с ним. Зачастую, это сайты, которые выдают содержимое или его часть с помощью AJAX. В общем-то, кеширование AJAX тоже возможно и даже нужно, но это тема для отдельного разговора и не касается традиционно используемых технологий, о которых пойдёт речь далее.Также, проблемы могут возникнуть у зарегистрированных пользователей, для которых постоянный кеш может стать проблемой при взаимодействии с элементами сайта. Тут, как правило, кеш отключается, либо используется объектное кеширование отдельных элементов сайта: виджетов, меню и тому подобных. Как настроить кеширование у себя на сайтеДля начала, надо разобраться какие технологии традиционно используются для кеширования содержимого сайтов.Все возможные способы можно разделить на 3 группы Кеширование на стороне сервераКеширование с помощью NGINXНа хостинге используется NGINX. Как правило, в качестве вебсервера работает связка NGINX + Apache. На мой взгляд, это наиболее удачный вариант для большинства сайтов и веб-проектов. NGINX используется как принимающий основную нагрузку кеширующий сервер, работающий во фротнэнде, Apache же работает с динамикой, собирая из скриптов html-страницу выдачи. Задачей NGINX является проверить, находится ли в кеше копия требуемой страницы (при работе в связке с Varnish или Memcached) либо её статичных элементов (стилей, скриптов, изображений, аудио- и видеофайлов и других медиа), их актуальность, и, если всё в порядке, отдать результат браузеру. Как можно настроить кеширование NGINX и WP Super Cache Если вы не используете NGINX, категорически рекомендую использовать его, он серьёзно повышает производительность сервера. Кеширование с помощью htaccess (Apache)Если у вас есть доступ только к .htaccess, и рабочий сервер только Apache, то вы можете использовать такие приёмы, как сжатие gzip и выставление HTTP заголовков Expires, чтобы использовать браузерный кеш. Включаем сжатие gzip для соответствующих MIME-типов файлов <IfModule mod_deflate.c> <IfModule mod_filter.c> AddOutputFilterByType DEFLATE text/plain text/html AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript AddOutputFilterByType DEFLATE text/xml application/xml application/xhtml+xml application/rss+xml AddOutputFilterByType DEFLATE application/json AddOutputFilterByType DEFLATE application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon </ifModule> </IfModule>Кеширование с помощью MemcachedСуть работы Memcached — сохранять данные в оперативную память и отдавать браузеру оттуда уже скомпилированную готовую страницу или её фрагменты. В принципе, туда можно сохранять всё, что угодно: результат «тяжёлых» запросов к базе данных, временно необходимые объекты и тому подобное. Так выходит намного быстрее, нежели чем читать даже статические html-файлы c hdd-диска, не говоря уже про постоянную генерацию страниц при каждом запросе к ним. Как установить и настроить Memcached Кеширование с помощью акселератора phpЕсли движок сайта написан на PHP, то при каждой загрузке любой страницы сайта происходит исполнение скриптов php: интерпретатор кода читает скрипты, написанные программистом, генерирует из них байткод, понятный машине, исполняет его и выдаёт результат. Акселератор PHP позволяет исключить постоянную генерацию байткода, кешируя скомпилированный код в памяти или на диске, тем самым увеличивая производительность и уменьшая время, затрачиваемое на исполнение PHP. Из поддерживаемых на сегодня акселераторов существует:
В PHP версии 5.5 и выше уже встроен акселератор Zend OPcache, поэтому чтобы включить акселератор, вам достаточно просто обновить версию PHP Кеширование на стороне сайтаКак правило, тут подразумевается возможность CMS сайта создавать статические html-копии страниц. Такой возможностью обладают большинство популярных движков и фреймворков. Лично я работал со Smarty, WordPress, поэтому могу заверить, что они отлично справляются со своей работой. В оригинальном WordPress из коробки нет кеширующих возможностей, которые необходимы любому малость нагруженному проекту, зато есть множество популярных плагинов для кеширования:
Что тут скажешь — используйте правильные CMS, и качественное кеширование будет доступно практически из коробки. Кеширование на стороне браузера (клиента), заголовки кешированияКеширование в браузере возможно потому, что любой уважающий себя браузер это позволяет и поощряет. Возможно это благодаря HTTP заголовкам, которые сервер отдаёт клиенту, а именно:
Благодаря им пользователи, которые неоднократно заходят на сайт, тратят крайне мало времени на загрузку страниц. Заголовки кеширования должны применяться ко всем кешируемым статическим ресурсам: файлы шаблона, картинок, файлы javascript и css, если есть, PDF, аудио и видео, и так далее.Рекомендуется выставлять заголовки так, чтобы статика хранилась не менее недели и не более года, лучше всего год. ExpiresЗаголовок Expires отвечает за то, как долго кеш является актуальным, и браузер может использовать кешированные ресурсы, не запрашивая у сервера их новую версию. Является сильным и крайне желательным к использованию, так как действует в обязательном порядке. В заголовке рекомендуется указывать срок от недели до года. Больше года лучше не указывать, это является нарушением правил RFC. Например, чтобы настроить Expires в NGINX для всех статических файлов на год (365 дней), в конфигурационном файле NGINX должен присутствовать код location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf)$ { expires 365d; }Чтобы настроить Expires в Apache для всех статических файлов на год (365 дней), в конфигурационном файле Apache, либо в .htaccess нужно прописать <IfModule mod_expires.c> <Filesmatch "\.(jpg|jpeg|png|gif|js|css|swf|ico|woff|mp3)$"> ExpiresActive on ExpiresDefault "access plus 365 days" </Filesmatch> </IfModule>Cache-Control: max-age;Cache-Control: max-age отвечает за то же самое.Более предпочтительно использование Expires, нежели Cache-Control ввиду большей распространённости. Однако, если Expires и Cache-Control будут присутствовать в заголовках одновременно, то приоритет будет отдан Cache-Control. В NGINX Cache-Control включается так же, как и Expires, директивой expires: 365d; Пример настройки Cache-Control в Apache при включённом кеширующем модуле mod_expires. <FilesMatch "\.(js|css|svg|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip)$"> Header set Cache-Control "max-age=2592000, must-revalidate" </FilesMatch>В данном примере, кеширующий заголовок включает кеш всех файлов, имеющих вышеперечисленные расширения сроком на 6 месяцев (2592000 секунд). Last-Modified и ETagЭти заголовки работают по принципу цифровых отпечатков. Это означает, что для каждого адреса URL в кеше будет устанавливаться свой уникальный id. Last-Modified создаёт его на основе даты последнего изменения. Заголовок ETag использует любой уникальный идентификатор ресурса (чаще всего это версия файла или хеш контента). Last-Modified – «слабый» заголовок, так как браузер применяет эвристические алгоритмы, чтобы определить, запрашивать ли элемент из кеша. В NGINX для статичных файлов ETag и Last-Modified включены по умолчанию. Для динамических страниц их либо лучше не указывать, либо это должен делать скрипт, генерирующий страницу, либо, что лучше всего, использовать правильно настроенный кеш, тогда NGINX сам позаботится о заголовках. Например, для WordPress, вы можете воспользоваться WP Super Cache. Эти заголовки позволяют браузеру эффективно обновлять кешированные ресурсы, отправляя запросы GET каждый раз, когда пользователь явным образом перезагружает страницу. Условные запросы GET не возвращают полный ответ, если ресурс не изменился на сервере, и таким образом обеспечивают меньшую задержку, чем полные запросы, тем самым уменьшая нагрузку на хостинг и уменьшая время ответа. Одновременное использование Expires и Cache-Control: max-age избыточно, так же, как избыточно одновременное использование Last-Modified и ETag. Используйте в связке Expires + ETag либо Expires + Last-Modified. Кстати, есть статья о том, как настроить Last-modified в WordPress Включить GZIP сжатие для статичных файловКонечно, сжатие GZIP не относится к кешированию как таковому напрямую, однако, весьма экономит трафик и увеличивает скорость загрузки страниц. Как включить GZIP для статики в NGINX server { .... gzip on; gzip_disable "msie6"; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; }Подробнее про настройку GZIP в NGINX Как включить GZIP для статики в .htaccess (Apache) Чтобы включить сжатие gzip в .htaccess, нужно в начало файла вставить следующий код: <IfModule mod_deflate.c> AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/x-javascript </IfModule>sheensay.ru Настройка предварительного сжатия и браузерного кэширования для блога на хостинге с Nginx и ApacheВ посте Как уменьшить нагрузку на сервер | оптимизация .htaccess приводились примеры директив для подключения предварительного сжатия и браузерного кэширования. Иногда такой способ оптимизации работы блога дает снижение нагрузки на хостинг и при достаточном объеме оперативной памяти уменьшает скорость загрузки страниц и потребляемый трафик. Проверить скорость загрузки страниц вы можете с помощью онлайнового сервиса Pingdom Tools.На не слишком загруженных сайтах благодаря браузерному кэшированию и предварительному сжатию данных можно и вовсе обойтись без плагинов кэширования. Однако в этом посте даны директивы, которые актуальны только для хостинга, на котором работает HTTP-сервер Apache. Некоторые хостеры ради экономии серверных ресурсов отключают Apache или вовсе не устанавливают его, предпочитая настраивать только менее прожорливый веб-сервер Nginx. Давайте посмотрим, как можно настроить предварительное сжатие и браузерное кэширование, если на вашем хостинге работает только Nginx. Предварительное сжатиеПеред тем, как отдать содержимое страниц в браузер посетителя, можно его сжать. Сжатие уменьшает размер передаваемых файлов (иногда в несколько раз), что приводит к увеличению скорости загрузки страниц и уменьшению исходящего трафика. Сжимать нужно только файлы, содержащие текстовую часть — текст, HTML, PHP, JS, XML, и прочие подобные. Текст хорошо сжимается даже при низком уровне компрессии, объем передаваемых фалов уменьшается на 50-80%. Конечно, файлы небольшие, всего десятки килобайт, но если учесть, что таких фалов тысячи, и загружаются они тысячами посетителей каждый день, то, как говорят, с миру по нитке — нищему на воротник, экономия получается существенная. Предварительное сжатие / ApacheДля тех, у кого установлен Apache, нужно узнать у хостера, какие специальные модули, реализующие его, установлены — mod_pagespeed или mod_deflate? Обычно в Apache 2x устанавливают mod_deflate. Есть еще mod_gzip, но его устанавливали в предыдущих версиях, так что его встретить маловероятно. Если установлен модуль mod_pagespeed, то в файл .htaccess, находящийся в корне вашего сайта, нужно вставить: ModPagespeed on # using commands,filters etc
Если установлен модуль mod_deflate, то то в файл .htaccess, находящийся в корне вашего сайта, нужно вставить: AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/css text/javascript application/javascript application/x-javascript
В данном случае сжатию подвергаются все текстовые файлы — txt, html, xml, xhtml, css, js. Предварительное сжатие / NginxЕсли хостинг работает под управлением Nginx, то директивы будут выглядеть иначе. В файл .htaccess, находящийся в корне вашего сайта, нужно вставить: server { gzip on; gzip_types text/html text/css application/x-javascript text/plain text/xml image/x-icon; }
Предварительное сжатие / СкриптБывает так, что сервер, обеспечивающий работу вашего блога, не поддерживает mod_deflate или mod_gzip. В этом случае можно прибегнуть к универсальному скрипту, который работает и на Apache, и на Nginx. В файл header.php используемой вами темы, в самое его начала, первой строкой нужно вставить: Итогом работы всех этих директив будет то, что браузер посетителя получить сжатый вариант страницы — он его скачает, распакует у себя во временных файлах, и отобразит в нормальном виде, а картинки вставить напрямую с сайта. Все современные барузеры умеют использовать сжатые варианты файлов, а те, которые еще не умеют, просто получат несжатые файлы. Браузерное кэшированиеНаряду со сжатием можно давать браузеру команду использовать кэшированную копию. Зачем каждый раз качать файлы с сайта, если они не с момента последнего посещения не изменились? Лучше отслеживать изменения файлов, и скачивать только те, которые им подверглись, а те, что остались с последнего захода на сайт не измененными, брать их кэша. Этот способ позволяет существенно сократить трафик между браузером посетителя и хостингом сайта, что приводит к сокращению времени загрузки страниц. Особенно заметен прирост в скорости на страницах с картинками. Действительно, картинки меняются на сайте очень редко, и зачем их каждый раз закачивать, есди они уже есть в кэше браузера? Браузерное кэширование / установки заголовков / ApacheApache обеспечивает браузерное кэширование с помощью модулей mod_expires и mod_headers: mod_expires определяет время актуальности кэшированных данных, а mod_headers — их публичную доступность. Совместная работа приводит к гибкой проверке данных перед скачиванием: браузер получает специальные заголовки, по ним определяет, устарели ли данные, которые находятся у него в кэше с момента последнего посещения страницы, и если они устарели, то обновляет их, закачивания новые версии файлов, а если не устарели, то отображает файлы из своего кэша, не скачивая с сервера. Если у вас работает Apache, для установки заголовков Expires добавьте в файл .htaccess: ExpiresActive On ExpiresDefault "acodeess plus 5 seconds" ExpiresByType image/x-icon "acodeess plus 2592000 seconds" ExpiresByType image/jpeg "acodeess plus 2592000 seconds" ExpiresByType image/png "acodeess plus 2592000 seconds" ExpiresByType image/gif "acodeess plus 2592000 seconds" ExpiresByType application/x-shockwave-flash "acodeess plus 2592000 seconds" ExpiresByType text/css "acodeess plus 604800 seconds" ExpiresByType text/javascript "acodeess plus 216000 seconds" ExpiresByType application/javascript "acodeess plus 216000 seconds" ExpiresByType application/x-javascript "acodeess plus 216000 seconds" ExpiresByType text/html "acodeess plus 600 seconds" ExpiresByType application/xhtml+xml "acodeess plus 600 seconds"
В данном случае актуальность кэша для разных фалов указана в секундах. Если у вас работает Apache, для установки заголовка Cache-control добавьте в файл .htaccess: Header set Cache-Control "public" Header set Cache-Control "public" Header set Cache-Control "private" Header set Cache-Control "private, must-revalidate"
В данном случае проверяется актуальность в кэше файлов ico, jpg, jpeg, png, gif, swf, css, js, html, xhtml, php. Браузерное кэширование / NginxЕсли у вас нет Apache, но есть Nginx, то для того, чтобы указать браузеру брать закэшированные данные, нужно вставить в файл .htaccess: location ~* .(jpg|png|gif|jpeg|css|js)$ { expires 24h; }
В данном случае актуальность кэша 24 часа, а типы проверяемых файлов указаны перечислением — jpg, png, gif, jpeg, css, js. n-wp.ru Подводные камни при использовании кэширования в nginxВ web-сервер и reverse-proxy nginx встроены очень мощные возможности по кэшированию HTTP-ответов. Однако в ряде случаев документации и примеров не хватает, в результате не все получается так легко и просто, как хотелось бы. Например, мои конфиги nginx-а местами написаны кровью. Этой статьей я попробую немного улучшить ситуацию.Я буду предполагать, что вы используете связку nginx+fastcgi_php. Если вы применяете nginx+apache+mod_php, просто замените имена директив с fastcgi_cache* на proxy_cache*, а также внесите изменения в следующие директивы (чтобы уменьшить объем кэша): proxy_cache_key "$request_method|$host|$request_uri";proxy_set_header If-Modified-Since "";proxy_set_header If-None-Match ""; Приведенный вариант работает во всех версиях nginx, начиная с 0.7.x (хотя в 0.8.31 и старше его можно упростить).Если выбирать, кэшировать ли страницу на стороне 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" "Set-Cookie";}} Это как раз пример строчки, написанной кровью. Здесь много подводных камней, давайте их все рассмотрим. 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. Он выдается с пустым телом ответа в двух случаях:
В обоих случаях 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. Я привел минимальное рабочее значение этой директивы. Шаг вправо, шаг влево, и вы начнете в ряде случаев получать "неправильные" данные из кэша. Итак:
fastcgi_hide_header: решаем проблемы с безопасностьюfastcgi_hide_header "Set-Cookie";Директива fastcgi_hide_header очень важна. Без нее вы серьезно рискуете безопасностью: пользователи могут получить чужие сессии через сессионную Cookie в кэше. (Правда, в последних версиях nginx что-то было сделано в сторону автоматического учета данного фактора.) Понимаете, как это происходит? На сайт зашел Вася Пупкин, ему выдалась сессия и сессионная Cookie. Пусть кэш на тот момент оказался пустым, и в него записалась Васина Cookie. Затем пришел другой пользователь, получил ответ из кэша, а в нем - и Cookie Васи. А значит, и его сессию тоже.
fastcgi_ignore_headers: не даем сайту "лечь" от нагрузки при опечаткеfastcgi_ignore_headers "Cache-Control" "Expires" "Set-Cookie";Сервер nginx обращает внимание на заголовки Cache-Control, Expires и Pragma, которые выдает PHP. Если в них сказано, что страницу не нужно кэшировать (либо что она уже устарела), то nginx не записывает ее в кэш-файл. Это поведение, хотя и кажется логичным, на практике порождает массу сложностей. Поэтому мы его блокируем: благодаря fastcgi_ignore_headers в кэш-файлы попадет содержимое любой страницы, независимо от ее заголовков. Что же это за сложности? Они опять связаны с сессиями и функцией session_start(), которая в PHP по умолчанию выставляет заголовки "Cache-Control: no-cache" и "Pragma: no-cache". Здесь существует три решения проблемы:
Кэширование с ротациейСтатическая главная страница — это не так уж и интересно. Что делать, если на сайте много материалов, а Главная выступает в роли своеобразной "витрины" для них? На такой "витрине" удобно отображать "случайные" материалы, чтобы разные пользователи видели разное (и даже один пользователь получал новый контент, перезагрузив страницу в браузере). Решение задачи —кэширование с ротацией:
В итоге первые 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" "Set-Cookie"; # Заставляем браузер каждый раз перезагружать страницу (для ротации).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 (см. выше).
Однако есть еще кэш в браузере. И в некоторых случаях браузер может даже не пытаться делать запрос на сервер, чтобы отобразить страницу; вместо этого он достанет ее из собственного кэша. Т.к. у нас ротация, нам такое поведение неудобно: ведь каждый раз, заходя на страницу, пользователь должен видеть новые данные. (На самом деле, если вы все же хотите закэшировать какой-нибудь один вариант, то можно поэкспериментировать с заголовком 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.
Почему же так важно выставлять текущим временем этот заголовок? Все довольно просто.
Есть и еще один повод выставлять Last-Modified вручную. Дело в том, что PHP-функция session_start() принудительно выдает заголовок Last-Modified, но указывает в нем... время изменения PHP-файла, который первый получил управление. Следовательно, если у вас на сайте все запросы идут на один и тот же скрипт (Front Controller), то ваша Last-Modified будет почти всегда равна времени изменения этого единственного скрипта, что совершенно не верно. Динамическое "окно" в закэшированной страницеНу и напоследок упомяну одну технику, которая может быть полезна в свете кэширования. Если вам хочется закэшировать главную (или любую другую) страницу сайта, однако мешает один маленький блок, который обязательно должен быть динамическим, воспользуйтесь модулем для работы с SSI. В ту часть страницы, которая должна быть динамической, вставьте вот такой "HTML-комментарий": <!--# include virtual="/get_user_info/" wait="no" -->С точки зрения кэша nginx данный комментарий — обычный текст. Он будет сохранен в кэш-файле именно в виде комментария. Однако позже, при прочтения кэша, сработает модуль SSI nginx, который обратится к динамическому URL. Конечно, по адресу /get_user_info/ должен быть PHP-обработчик, который выдает содержимое данного блока. Более подробно данный способ описан в этой статье. Ну и, естественно, не забудьте включить SSI для этой страницы или даже для всего сервера: ssi on;Директива SSI include имеет еще одно, крайне важное свойство. Когда на странице встречаются несколько таких директив, то все они начинают обрабатываться одновременно, в параллельном режиме. Так что, если у вас на странице 4 блока, каждый из которых загружается 200мс, в сумме страница будет получена пользователем примерно через 200мс, а не через 800. На самом деле, время будет чуть больше 200мс, т.к. надо учитывать загруженность остальных потоков nginx (возможно, на других машинах кластера, если запросы распараллеливаются по машинам) и издержки на переключение процессов. http://dklab.ru annenkov.org Настройка кэширования на Nginx | Let'sclearITupСуть кеширования на стороне сервера заключается в том, чтобы избавиться от постоянного запуска одних и те же скриптов (как пример, генерации ленты постов WordPress), выполнение которых может иногда занимать целые секунды. С использованием кэширования приложение сгенерирует страницу один раз и сохранит результат в память на какое-то время (называемое TTL). Пока не истечет TTL, клиент будет получать сохраненную в памяти версию страницы. Давайте разберемся с настройкой кэширования на Nginx! Преимущества кэширования Nginx по сравнению с Varnish состоят прежде всего в простоте настройки. Оптимально использовать кэширование для сайтов с контентом, который доступен неавторизованным пользователям (публичный). Считаем, что Nginx у нас установлен из пакетов (или собран из исходников) и настроен. Для включения кэширования в Nginx сначала необходимо определить максимальный размер кеша (общий размер всех страниц в кеше не может превышать это значение). Сделать это можно в конфигурационном файле /etc/nginx/nginx.conf с помощью директивы в секции http: ... proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=all:32m; ...Не забываем создать каталог для кеширования, который мы указали выше: mkdir /var/cache/nginxДалее следует изменить настройки сайта, создав еще одну секцию server. Переносим наш основной сервер на другой порт (например, 81), а на стандартном 80 у нас теперь будет работать кэширующий хост, который либо будет отдавать данные из кэша, либо перенаправлять запросы на основной хост. Это может выглядеть примерно так: 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 / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; access_log /var/log/nginx/letsclearitup.access.log; error_log /var/log/nginx/letsclearitup.error.log error; location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/run/php/letsclearitup.sock; fastcgi_hide_header X-Powered-By; } location /status { fastcgi_pass unix:/run/php/letsclearitup.sock; include fastcgi.conf; allow 127.0.0.1; deny all; } }Если у пользователя установлены какие-либо Cookies, кэширование можно отключить: server { listen 80; location / { if ($http_cookie ~* ".+" ) { set $do_not_cache 1; } proxy_pass http://127.0.0.1:81/; proxy_cache all; proxy_cache_valid any 1h; # Кешируем на 1 час } }Есть смысл включать кэширование также и для ошибочных запросов, чтобы снизить нагрузку от обращений к неработающей части сайта: server { listen 80; location / { if ($http_cookie ~* ".+" ) { set $do_not_cache 1; } proxy_pass http://127.0.0.1:81/; proxy_cache all; proxy_cache_valid 404 502 503 1m; proxy_cache_valid any 1h; # Кешируем на 1 час } }У Nginx есть возможность кеширования ответов от fastcgi. Чтобы использовать данную возможность, в секции http файла /etc/nginx/nginx.conf добавляем: ... fastcgi_cache_path /var/cache/fpm levels=1:2 keys_zone=fcgi:100m; fastcgi_cache_key "$scheme$request_method$host$request_uri"; ...Создаем каталог: mkdir /var/cache/fpmПосле чего в настройках сайта (в секции server для основного хоста) добавим такие строки: server { listen 81; ... location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/run/php/letsclearitup.sock; fastcgi_hide_header X-Powered-By; fastcgi_cache fcgi; fastcgi_cache_valid 200 60m; # кешировать ответы с кодом 200 на 1 час } ... }Настройка кэширования на Nginx довольно проста, но если все сделать правильно, то можно получить десятикратное ускорение сайта и неплохую экономию ресурсов. letsclearitup.com.ua |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|