Поиск по сайту:

Как настроить кэширование FastCGI с помощью Nginx на вашем VPS


Прелюдия

Nginx включает в себя модуль FastCGI с директивами для кэширования динамического контента, который обслуживается из серверной части PHP. Настройка этого устраняет необходимость в дополнительных решениях для кэширования страниц, таких как обратные прокси-серверы (например, Varnish) или плагины для конкретных приложений. Контент также можно исключить из кэширования на основе метода запроса, URL-адреса, файлов cookie или любых других переменных сервера.

Включение кэширования FastCGI на вашем VPS

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

nano /etc/nginx/sites-enabled/vhost

Добавьте следующие строки в начало файла вне директивы server { }:

fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=MYAPP:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

Директива \fastcgi_cache_path указывает расположение кеша (/etc/nginx/cache), его размер (100 м), имя зоны памяти (MYAPP), уровни подкаталогов и таймер inactive\\.

Расположение может быть где угодно на жестком диске; однако размер должен быть меньше, чем RAM + Swap вашей капли, иначе вы получите сообщение об ошибке «Не удается выделить память». Мы рассмотрим параметр «уровни» в разделе очистки — если доступ к кешу не осуществляется в течение определенного периода времени, указанного параметром «неактивный» (здесь 60 минут), то Nginx удаляет его.

Директива «fastcgi_cache_key» указывает, как будут хешироваться имена файлов кэша. Nginx шифрует доступный файл с помощью MD5 на основе этой директивы.

Затем переместите директиву location, которая передает PHP-запросы, в php5-fpm. Внутри \location ~ .php${ } добавьте следующие строки.

fastcgi_cache MYAPP;
fastcgi_cache_valid 200 60m;

Директива «fastcgi_cache» ссылается на имя зоны памяти, которое мы указали в директиве «fastcgi_cache_path», и хранит кеш в этой области.

По умолчанию Nginx хранит кэшированные объекты в течение времени, указанного любым из этих заголовков: X-Accel-Expires/Expires/Cache-Control.

Директива «fastcgi_cache_valid» используется для указания времени жизни кэша по умолчанию, если эти заголовки отсутствуют. В операторе, который мы ввели выше, кэшируются только ответы с кодом состояния 200. Также можно указать другие коды ответов.

Проведите тест конфигурации

service nginx configtest

Перезагрузите Nginx, если все в порядке

service nginx reload

Полный файл vhost будет выглядеть так:

fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=MYAPP:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

server {
    listen   80;
    
	root /usr/share/nginx/html;
	index index.php index.html index.htm;

	server_name example.com;

	location / {
	    try_files $uri $uri/ /index.html;
    }

	location ~ \.php$ {
	    try_files $uri =404;
	    fastcgi_pass unix:/var/run/php5-fpm.sock;
	    fastcgi_index index.php;
	    include fastcgi_params;
	    fastcgi_cache MYAPP;
	    fastcgi_cache_valid 200 60m;
    }
}

Далее мы проверим, работает ли кэширование.

Тестирование кэширования FastCGI на вашем VPS

Создайте файл PHP, который выводит временную метку UNIX.

 /usr/share/nginx/html/time.php

Вставлять

<?php
echo time();
?>

Запросите этот файл несколько раз с помощью curl или веб-браузера.

root@droplet:~# curl http://localhost/time.php;echo
1382986152
root@droplet:~# curl http://localhost/time.php;echo
1382986152
root@droplet:~# curl http://localhost/time.php;echo
1382986152

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

Сделайте рекурсивный список местоположения кеша, чтобы найти кеш этого запроса.

root@droplet:~# ls -lR /etc/nginx/cache/
/etc/nginx/cache/:
total 0
drwx------ 3 www-data www-data 60 Oct 28 18:53 e

/etc/nginx/cache/e:
total 0
drwx------ 2 www-data www-data 60 Oct 28 18:53 18

/etc/nginx/cache/e/18:
total 4
-rw------- 1 www-data www-data 117 Oct 28 18:53 b777c8adab3ec92cd43756226caf618e

Соглашение об именах будет объяснено в разделе очистки.

Мы также можем заставить Nginx добавить к ответу заголовок \X-Cache, указывающий, был ли кеш пропущен или попал.

Добавьте следующее над директивой server { }:

add_header X-Cache $upstream_cache_status;

Перезагрузите службу Nginx и выполните подробный запрос с помощью curl, чтобы увидеть новый заголовок.

root@droplet:~# curl -v http://localhost/time.php
* About to connect() to localhost port 80 (#0)
*   Trying 127.0.0.1...
* connected
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /time.php HTTP/1.1
> User-Agent: curl/7.26.0
> Host: localhost
> Accept: */*
>
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Server: nginx
< Date: Tue, 29 Oct 2013 11:24:04 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Cache: HIT
<
* Connection #0 to host localhost left intact
1383045828* Closing connection #0

Настройка исключений кэша

Некоторое динамическое содержимое, такое как страницы, требующие аутентификации, не должно кэшироваться. Такой контент может быть исключен из кэширования на основе переменных сервера, таких как \request_uri, \request_method и \http_cookie.

Вот пример конфигурации, которую необходимо использовать в контексте server{ }.

#Cache everything by default
set $no_cache 0;

#Don't cache POST requests
if ($request_method = POST)
{
    set $no_cache 1;
}

#Don't cache if the URL contains a query string
if ($query_string != "")
{
    set $no_cache 1;
}

#Don't cache the following URLs
if ($request_uri ~* "/(administrator/|login.php)")
{
    set $no_cache 1;
}

#Don't cache if there is a cookie called PHPSESSID
if ($http_cookie = "PHPSESSID")
{
    set $no_cache 1;
}

Чтобы применить переменную \$no_cache к соответствующим директивам, поместите следующие строки внутри location ~ .php${ }

fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $no_cache;

Директива \fasctcgi_cache_bypass игнорирует существующий кэш для запросов, связанных с заданными нами ранее условиями. Директива \fastcgi_no_cache вообще не кэширует запрос, если выполняются заданные условия.

Очистка кэша

Соглашение об именах кеша основано на переменных, которые мы установили для директивы «fastcgi_cache_key».

fastcgi_cache_key "$scheme$request_method$host$request_uri";

Согласно этим переменным, когда мы запрашивали \http://localhost/time.php, фактическими значениями были бы следующие:

fastcgi_cache_key "httpGETlocalhost/time.php";

Передача этой строки через хеширование MD5 выведет следующую строку:

b777c8adab3ec92cd43756226caf618e

Это сформирует имя файла кеша, как для подкаталогов, которые мы ввели \levels=1:2. Следовательно, первый уровень каталога будет иметь имя с символом 1 из последней строки этой MD5, которая является e; второй уровень будет иметь последние 2 символов после первого уровня, т. е. 18. Следовательно, вся структура каталогов этого кэша выглядит следующим образом:

/etc/nginx/cache/e/18/b777c8adab3ec92cd43756226caf618e

На основе этого формата именования кеша вы можете разработать сценарий очистки на своем любимом языке. Для этого урока я предоставлю простой PHP-скрипт, который очищает кеш URL-адреса __POST__ed.

/usr/share/nginx/html/purge.php

Вставлять

<?php
$cache_path = '/etc/nginx/cache/';
$url = parse_url($_POST['url']);
if(!$url)
{
    echo 'Invalid URL entered';
    die();
}
$scheme = $url['scheme'];
$host = $url['host'];
$requesturi = $url['path'];
$hash = md5($scheme.'GET'.$host.$requesturi);
var_dump(unlink($cache_path . substr($hash, -1) . '/' . substr($hash,-3,2) . '/' . $hash));
?>

Отправьте POST-запрос к этому файлу с URL-адресом для очистки.

curl -d 'url=http://www.example.com/time.php' http://localhost/purge.php

Сценарий будет выводить true или false в зависимости от того, был ли очищен кеш или нет. Обязательно исключите этот скрипт из кэша, а также ограничьте доступ.

Представлено: Джесин А