opened image

Настройка FastCGI Microcache в Nginx PHP-FPM

Преимущество FastCGI MicroCache в том, что при запросе от сервера, ответ кешируется для пользователя, и уже доступен в выделенной области на диске и в RAM.

Это большое преимущество, так как снимает нагрузку с сервера при большом количестве запросов к одной странице.

Это касается тех страниц, которые не изменяются, или изменяются редко. 


Предположим большое количество пользователей одновременно просматривают главную страницу. Ответ от сервера для всех пользователей будет составлять около 2 сек до первого байта. Это связано с тем что серверу необходимо обработать данный запрос и только после - выдать его. 

Чтобы уменьшить ответ до первого байта, используем FastCGI Microcache.

В начале, мой конфиг сайта выглядит примерно так:
 


                    server {
                        listen      xx.xx.xx.xx:443 ssl http2;
                        server_name site.com www.site.com;
                        root        /home/admin/web/site.com/public_html;
                        index       index.php index.html index.htm;

                        ssl_certificate      /home/admin/conf/web/ssl.site.com.pem;
                        ssl_certificate_key  /home/admin/conf/web/ssl.site.com.key;

                        location / {
                        
                            try_files $uri $uri/ /index.php?$query_string;


                        }


А серверный конфиг /etc/nginx/nginx.conf так:

 

 

 


                    # Server globals
                    user                    nginx;
                    worker_processes        auto;
                    worker_rlimit_nofile    65535;


                    # Worker config
                    events {
                            worker_connections  1024;
                            use                 epoll;
                            multi_accept        on;
                    }


                    http {




                        # Compression
                        gzip                on;
                        gzip_vary           on;
                        gzip_comp_level     5;
                        ....
                        ....
                     
                    }

 


Для начала необходимо определить место и задать параметры хранения кэшированных запросов. 

В серверный конфиг (в моем случае /etc/nginx/nginx.conf) в блок http добавляем следующую конструкцию:

 

 

 

 

fastcgi_cache_path /tmp/nginx_microcache levels=1:2 keys_zone=microcache:10m max_size=500m inactive=1h;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

 




Где:

        fastcgi_cache_path — определяет расположение кеша на сервере. Даная директория будет очищаться при каждом перезапуске севера. То что будет хранится в данной папке, так же будет занимать место в ОЗУ. 

        levels=1:2 — устанавливает двухуровневую иерархию каталогов в папке /tmp/nginx_microcache

        keys_zone — задать имя зоны (Вы можете указать свои предпочтения)

        keys_zone=microcache:10m - 10m —  размер зоны (таких зоно может быть множество для каждого сайта в отдельности если это необходимо). 

        max_size=500m  - размер пространства которое будет занимать кеш. (Выделяется область в ОЗУ. Главное не перестараться.)  Его размер должен быть меньше, чем системная оперативная память + подкачка. Иначе возможна ошибка «Не удается выделить память».


        inactive — задает время, по истечении которого кеш который находиться в /tmp/nginx_microcache и в ОЗУ, к которым не обращались, в течение того времени которое указано (1 час), удаляются из кеша. (По умолчанию inactive=10m)


        Далее необходимо задать ключи которые будут указывать какие запросы необходимо кешировать. Это задает директива  fastcgi_cache_key.

        fastcgi_cache_key — определяет какие будут кешироваться запросы.


        Переменные, используемые в factcgi_cache_key

        $scheme – схема запроса HTTPS или HTTP
        $request_method — указывает методы запроса, такие как GET или POST.
        $host – Имя сервера, соответствующего запроса
        $request_uri — Полный URI запроса

Теперь что бы подключить выбранную область к нашему сайту, необходимо в его конфиг в моем случае (/home/admin/conf/web/xxxxx.xxx.nginx.ssl.conf) в блок location / добавить следующую конструкцию:

 

 

 

 

location / {

#MicroCache
                    
                    fastcgi_cache microcache;
                    fastcgi_cache_lock on;
                    fastcgi_cache_valid 200 10s;
                    fastcgi_cache_use_stale updating;
                    
                    # Security Header
                    
                    add_header X-FastCGI-Cache $upstream_cache_status;  #Показывает статус кеша в блоке Header


                    #Задаем условия, при которых ответ не будет браться из кэша.
                    
                    fastcgi_cache_bypass $no_cache; #Определяем переменную $no_cache
                    fastcgi_no_cache $no_cache;     #Определяем переменную $no_cache

                        set $no_cache 0;                                             # исключить из кэширования
                        if ($request_method = POST) { set $no_cache 1; }
                        if ($request_method !~ ^(GET|HEAD)$) { set $no_cache "1"; }


                        if ($query_string != "") { set $no_cache 1; }
                        if ($request_uri ~* "/admin") { set $no_cache 1; }        # исключить из кэширования /admin

        }
}

 



Директивой fastcgi_cache - задаем то же имя зоны которое определено в серверном конфиге. В моем случае microcache. (Для каждого отдельного сайта можно задавать свои зоны)
fastcgi_cache_valid - определяет время кэширования в зависимости от кода состояния HTTP (200, 301, 302). В приведенном выше примере ответы с кодом состояния 200 будут кэшироваться на 10 секунд. Вы также можете использовать период времени, например 12h(12 часов) и 7d(7 дней). 
Для динамического контента, такого как, админка любой CMS, этого делать крайне не желательно. 
В блоке # Security Header определены заголовки add_header X-FastCGI-Cache $upstream_cache_status; которые показывают статус запроса, закеширована страница или нет. MISS, BYPASS, EXPIRED, и HIT - чаще всего встречающиеся заголовки. 
    Значение HIT можно наблюдать, когда страница получена из кэша. Если в заголовке EXPIRED - то это говорит о том что кеш для данного запроса или страницы устарел, то-есть выделенное время которое описано в директиве fastcgi_cache_valid в моем случае 10 секунд - вышло. 
    Статус BYPASS - можем наблюдать когда запрос/страница не кешируется. Правила того что не будет попадать в кеш описаны в блоке #Задаем условия, при которых ответ не будет браться из кэша. В моем случае (любая CMS) и все страницы /admin в админ панели не будут кешироваться. Это важно, так как здесь контент постоянно изменяется. 
    Статус MISS означает что страница не кешируется. 

 

 

 

 

 

 


					[root@a48zomro ~]# curl -I https://site.com/
                    HTTP/1.1 200 OK
                    Server: nginx
                    Date: Sun, 29 May 2022 11:13:13 GMT
                    ....
                    ....
                    X-FastCGI-Cache: MISS

                    
                    [root@a48zomro ~]# curl -I https://site.com/
                    HTTP/1.1 200 OK
                    Server: nginx
                    Date: Sun, 29 May 2022 11:13:23 GMT
                    ....
                    ....
                    X-FastCGI-Cache: HIT

                    [root@a48zomro ~]# curl -I https://site.com/admin/
                    HTTP/1.1 302 Found
                    Server: nginx
                    Date: Sun, 29 May 2022 11:13:32 GMT
                    ....
                    ....
                    X-FastCGI-Cache: BYPASS

                    [root@a48zomro ~]# curl -I https://site.com/
                    HTTP/1.1 200 OK
                    Server: nginx
                    Date: Sun, 29 May 2022 11:13:39 GMT
                    ....
                    ....
                    X-FastCGI-Cache: EXPIRED

 


При данной настройке, наш сайт будет кешироваться и ответ до первого байта может достигать до 2 мс

До оптимизации:


После оптимизации: