[PHP, Nginx] Использование Nginx FastCGI Cache

Автор Сообщение
news_bot ®

Стаж: 6 лет 7 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
29-Сен-2020 14:30

FastCGI Cache — это система кэширования данных реализованая на уровне HTTP-сервера Nginx.Преимущество FastCGI Cache заключается в том, что Nginx вернёт закешированный ответ пользователю сразу, как только получит запрос, при этом слой приложения не будет вовсе обрабатывать поступивший HTTP-запрос, если он имеется в кэше Nginx. Использование FastCGI Cache — отличный способ снизить нагрузку на вашу систему.Если на вашем сайте есть страницы, которые изменяются редко или задержка обновления информации на некоторое время не критична, то FastCGI Cache именно то, что нужно.Схема работы Nginx FastCGI CacheЕсли на сервер Nginx пришёл HTTP-запрос и некоторое время назад ответ на такой же запрос был помещён в кэш, то Nginx не станет передавать данный запрос на выполнение PHP-FPM, в место этого Nginx вернёт результат из кэша.
ЗадачаПредположим у нас есть web-система управления полётом на луну, которая написана на PHP. Каждый пользователь должен ввести свой логин и пароль, чтобы войти в систему и оказаться на главной странице космического приложения. Главная страница нашего ресурса, на которую попадают пользователи прошедшие этап аутентификации, очень популярная. Все пользователи ежедневно многократно просматривают эту страницу. На ней выводится большое количество всевозможных данных. Чтобы сгенерировать эту страницу требуется выполнить порядка тридцати SQL-запросов в различные базы данных.Важно отметить, у пользователей данные, которые они видят на главной странице могут отличаться. Нам известно, что информация, которая выводится на этой странице может обновляться с задержкой в один час. Данные не потеряют свою ценность даже есть они немного устареют.Что из этого следует?
  • У каждого пользователя, прошедшего аутентификацию должна быть своя версия кэша главной страницы.
  • До ввода логина и пароля и после этого главная страница системы выглядит по-разному. Не прошедшие аутентификацию пользователи видят только форму для входа в систему.
  • Мы можем хранить данные в кэше в течение 1 часа.
Решение Изначально наш виртуальных хост сконфигурирован следующим образом:
http {
    include /etc/nginx/mime.types;
    server {
        listen 80;
        index index.php index.html;
        server_name moon-flight.aero;
        error_log /var/log/nginx/moon-flight.aero.error.log;
        access_log /var/log/nginx/moon-flight.aero.access.log
        root /var/www/moon-flight.aero/public;
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_script_name;
        }
    }
}
Первое, что мы сделаем добавим директиву fastcgi_cache_path в в контексте http.
fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=fastcgicache:10m inactive=70m max_size=512m;
Первый аргумент /tmp/nginx_cache определяет место на сервере, где будет сохранён кэш. Папка /tmp нам подходит, так как она очищается автоматически при перезапуске сервера. Важно отметить, что всё, что будет хранится в /tmp/nginx_cache так же будет находится в оперативной памяти.Второй аргумент — это уровень подпапок. Мы указали levels=1:2. Это означает, что уровень вложенности будет равняться 2.Нас это устраивает, так как в одной папке у нас не будет большого количества файлов, а значит и замедление доступа к файлам нам не грозит.Третий аргумент — имя зоны разделяемой памяти кэша. Запись keys_zone=fastcgicache:10m означает, что названием зоны является fastcgicache, а 10m — это размер зоны в мегабайтах. Зона размеров в 10 Мб может хранить данные для примерно 80 000 ключей. Конечно, название зоны может быть другим.Четвёртый аргумент — inactive=70m, определяет интервал времени, после истечении которого данные автоматически удаляются, в случае, если они не используются. Другими словами, если к данным кэша не обращаются в течение времени, заданного параметром inactive, то данные удаляются, независимо от их свежести. По умолчанию inactive равен 10 минутам.Пятый аргумент max_size=512m — устанавливает верхний предел размера кэша. По умолчанию используется всё дисковое пространство. При достижении лимита, Nginx удалит наименее востребованные данные.Далее мы должны задать ключ для кэширования данных. Это можно сделать при помощи директивы fastcgi_cache_key. Данная директива может быть указана в контекстах httpserver и location.Укажим в контексте server директиву fastcgi_cache_key:
fastcgi_cache_key "$scheme$request_method$host$request_uri$cookie_codeAuth";
Здесь мы указали несколько переменных:— $scheme — $request_method— $host $request_uri— $cookie_codeAuthДавайте разберёмся с ними подробнее. Нам важно понимать, какие значения будут принимать эти переменные. Рассмотрим пример, допустим залогиненный пользователь указал в браузере такой запрос:http://moon-flight.aero/search/?query=10После выполнения этого запроса Nginx присвоит следующие значения нашим переменным:ПеременнаяЗначение$schemehttp$request_methodGET$hostmoon-flight.aero$request_uri/search/?query=10$cookie_codeAuthБудет иметь значение параметра Cookie codeAuth, который был передан браузером в заголовках запроса. В вашей системе аналогичная переменная Cookie может называть по-другому.В нашем случае у каждого пользователя, который успешно прошёл процедуру аутентификации в Cookie имеется переменная codeAuth. Эта переменная определяет активную сессию аутентификации. Nginx позволяет получать значение переменных Cookie, для этого мы должны использовать такой шаблон$cookie_имя.В нашем примере мы исходим из того, что заголовках HTTP-запроса присутствует подобная строка:Cookie: codeAuth=a7e30fbb7f4513redfd22049c6b5dzme306f4eКлюч "$scheme$request_method$host$request_uri$cookie_codeAuth" выглядит не очень изящно, но он даёт нам возможность для каждого пользователя, который заходит на страниц сайта сформировать свой собственный кэш. Значение переменной $cookie_codeAuth для каждого залогиненного пользователя будет уникальным.Двигаемся дальше. Теперь нам нужно описать условия работы кэша в контексте server и определить директивы fastcgi_cachefastcgi_cache_validfastcgi_cache_bypass и fastcgi_no_cache в контексте location.Опишем условия работы нашего кэша в контексте server.Мы хотим кэшировать:
  • Только главную страницу, то есть переменная $request_uri должна иметь значение "/".
  • Запросы типа GET и никакие другие. Следовательно значение переменной $request_method должно равняться GET.
  • Только те запросы, в которых нет GET параметров. Значит переменная $query_string должна содержать пустую строку "".
Эти 3 условия мы запишем так (в контексте server):
set $no_cache 0;
if ($request_method != GET) {
     set $no_cache 1;
}
if ($query_string != "") {
     set $no_cache 1;
}
if ($request_uri != "/") {
     set $no_cache 1;
}
Теперь определим директивы fastcgi_cache, fastcgi_cache_valid, fastcgi_cache_bypass и fastcgi_no_cache в контексте location.
fastcgi_cache fastcgicache;
fastcgi_cache_valid 200 60m;
fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $no_cache;
Что значат эти директивы?fastcgi_cache — задаёт название зоны разделяемой памяти, используемой для кэширования. Название зоны мы указывали ранее в директиве fastcgi_cache_path.fastcgi_cache_valid — задаёт время кэширования HTTP-кода ответа. В нашем случае мы установили время равно 60 минут для кода 200.fastcgi_cache_bypass — задаёт условие, при котором ответ не будет браться из кэша. Если значение непустое или не равно 0, то ответ не берётся из кэша.fastcgi_no_cache — задаёт условия, при котором ответ не будет сохраняться в кэш. Если значение непустое или не равно 0, то ответ не будет сохранён в кэше.Файл конфигурации можно сохранить и выполнить команду:sudo service nginx reloadВсё должно работать.Но как узнать, что данные кэшируются и мы получаем результат из кэша?Очень просто. Нужно добавить специальный заголовок, и передать в него переменную $upstream_cache_status. В секцию server добавим директиву add_header со следующими параметрами:
add_header x-fastcgi-cache $upstream_cache_status;
x-fastcgi-cache — это название нашего заголовка. Переменная $upstream_cache_status может иметь следющие значения: 
  • MISS
  • BYPASS
  • EXPIRED
  • STALE
  • UPDATING
  • REVALIDATED
  • HIT
Если страница получена из кэша, то вы увидите значение HIT.Финальный файл конфигурации со всеми добавленными директивами будет выглядеть так:
http {
    include /etc/nginx/mime.types;
    fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=fastcgicache:10m inactive=70m max_size=512m;
    server {
        listen 80;
        index index.php index.html;
        server_name moon-flight.aero;
        error_log /var/log/nginx/moon-flight.aero.error.log;
        access_log /var/log/nginx/moon-flight.aero.access.log
        root /var/www/moon-flight.aero/public;
        fastcgi_cache_key "$scheme$request_method$host$request_uri$cookie_codeAuth";
        set $no_cache 0;
        if ($request_method != GET) {
            set $no_cache 1;
        }
        if ($query_string != "") {
            set $no_cache 1;
        }
        if ($request_uri != "/") {
            set $no_cache 1;
        }
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
        add_header x-fastcgi-cache $upstream_cache_status;
        location ~ \.php$ {
            fastcgi_cache fastcgicache;
            fastcgi_cache_valid 200 60m;
            fastcgi_cache_bypass $no_cache;
            fastcgi_no_cache $no_cache;
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_script_name;
        }
    }
}
Полезные команды Проверить синтаксис файлов конфигурации Nginx можно следующей командой:sudo nginx -tДля того, чтобы изменения конфигурации вступили в силу, выполните:sudo service nginx reloadТестирование производительности при помощи Apache BenchУтилита Apache Bench позволяет проверить скорость работы веб-приложения. C помощью Apache Bench можно отправить заданное количество запросов на указанный адрес и при этом определить число запросов, которые будут отправлены одновременно. Так же есть возможность указать требуемые заголовки и передать значения переменных cookies.Установим Apache Bench на виртуальный сервер Ununtu.Выполним команду:sudo apt-get updateЗатем:sudo apt-get install apache2-utilsУсловия тестированияНам нужно зафиксировать производительность нашей системы управления полётом на луну с выключенным кэшем и с работающим.Запуск Apache Bench при выключенном кэшеЧтобы FastCGI Cache перестал работать нужно в нашем файле конфигурации виртуального хоста установить значение переменной $no_cache равным 1. После внесения изменений в конфигурацию не забудьте выполнить команду sudo service nginx reloadТеперь запустим тестирование. На виртуальном сервере, на котором установлен Apache Bench выполним команду:
ab -c 5 -n 100 -C "codeAuth=a7e30fbb7f4513redfd22049c6b5dzme306f4e" http://moon-flight.aero
На http://moon-flight.aero будет отправлено 100 запросов, при этом одновременно будет устанавливаться 5 подключений. Флаг -C используется для того, чтобы в запросе содержался параметр cookie codeAuth.Результат:
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking moon-flight.aero (be patient).....done
Server Software:        nginx/1.14.0
Server Hostname:        moon-flight.aero
Server Port:            80
Document Path:          /
Document Length:        31134 bytes
Concurrency Level:      5
Time taken for tests:   2.978 seconds
Complete requests:      100
Failed requests:        0
Total transferred:      3150400 bytes
HTML transferred:       3113400 bytes
Requests per second:    33.58 [#/sec] (mean)
Time per request:       148.878 [ms] (mean)
Time per request:       29.776 [ms] (mean, across all concurrent requests)
Transfer rate:          1033.25 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       23   29   5.0     27      50
Processing:    58  112  17.1    113     142
Waiting:       58  112  17.0    113     142
Total:         85  141  16.7    142     176
Percentage of the requests served within a certain time (ms)
  50%    142
  66%    149
  75%    154
  80%    159
  90%    163
  95%    166
  98%    170
  99%    176
100%    176 (longest request)
Потребовалось почти 3 секунды, чтобы выполнить 100 запросов. Скорость передачи — 33.58 запросов в секунду.Запуск Apache Bench при работающем кэшеЧтобы включить кэширование нужно в файле конфигурации виртуального хоста установить значение переменной $no_cache равным 0. После внесения изменений в конфигурацию не забудьте выполнить команду sudo service nginx reloadТеперь снова запустим тестирование:
ab -c 5 -n 100 -C "codeAuth=a7e30fbb7f4513redfd22049c6b5dzme306f4e" http://moon-flight.aero
Результат будет следующий:
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking moon-flight.aero (be patient).....done
Server Software:        nginx/1.14.0
Server Hostname:        moon-flight.aero
Server Port:            80
Document Path:          /
Document Length:        31134 bytes
Concurrency Level:      5
Time taken for tests:   1.068 seconds
Complete requests:      100
Failed requests:        0
Total transferred:      3150104 bytes
HTML transferred:       3113400 bytes
Requests per second:    93.64 [#/sec] (mean)
Time per request:       53.398 [ms] (mean)
Time per request:       10.680 [ms] (mean, across all concurrent requests)
Transfer rate:          2880.52 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       23   31   6.5     27      47
Processing:    14   17   7.8     16      93
Waiting:       14   17   7.8     16      93
Total:         37   47  10.1     44     122
Percentage of the requests served within a certain time (ms)
  50%     44
  66%     49
  75%     52
  80%     54
  90%     56
  95%     61
  98%     63
  99%    122
100%    122 (longest request)
Потребовалась всего 1 секунда, чтобы выполнить 100 запросов. Скорость передачи теперь — 93.64 запросов в секунду.Использованные материла и полезные ссылки:Описание модуля ngx_http_fastcgi_module доступно по ссылке: http://nginx.org/ru/docs/http/ngxhttpfastcgi_module.htmlВидео о том, как настроить FastCGI Cache Nginx: https://www.youtube.com/watch?v=Nri2KOI3HJo&t=66sДокументация Apache Bench: https://httpd.apache.org/docs/2.4/programs/ab.html
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_php, #_nginx, #_nginx, #_fastcgi, #_php, #_phpfpm, #_cache, #_php, #_nginx
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 06-Окт 03:41
Часовой пояс: UTC + 5