От переводчика:
Речь пойдет о тонкостях настройки связки Nginx + PHP-FPM в виде небольшого сборника советов. Перевод вольный. Ориентированно на пользователей Linux.
Советы по настройке и оптимизации Nginx
Совет №1 — Организация файлов конфигурации Nginx
Обычно файлы конфигурации Nginx хранятся в /etc/nginx
.
Один из удобных способов организации файлов конфигурации в стиле Debian/Ubuntu Apache:
1 2 3 4 5 6 7 8 9 |
## Главный файл конфигурации /etc/nginx/nginx.conf ## Файлы конфигурации вируальных хостов (virtualhost) ## /etc/nginx/sites-available/ /etc/nginx/sites-enabled/ ## Другие файлы конфигурации (если необходимы) ## /etc/nginx/conf.d/ |
Файлы виртуальных хостов разделены на две директории. Директория sites-available
может содержать любые файлы: тестовые, старые конфиги, копии конфигов и прочие. А директория sites-enabled
содержит только реально работающие конфигурации, в действительности являющиеся только символическими ссылками на файлы в директории sites-available
.
Не забудьте добавить следующие строки в файл nginx.conf
:
1 2 3 4 5 |
## Загрузка файлов конфигарации виртуальных хостов ## include /etc/nginx/sites-enabled/*; ## Загрузка других конфигов из conf.d/ ## include /etc/nginx/conf.d/*; |
Совет №2 — Определить Nginx worker_processes и worker_connections
Настройки по умолчанию хороши, но их стоит немного оптимизировать: max_clients = worker_processes * worker_connections
.
Базовые настройки Nginx могут обрабатывать сотни одновременных соединений:
1 2 |
worker_processes 1; worker_connections 1024; |
Обычно 1000 одновременных соединений на один сервер это хорошо, но порою другие части, например жесткий диск могут оказаться медленными и это приведет к тому, что Nginx будет заблокирован на операции ввода-вывода (I/O). Чтобы избежать блокировки используйте, например, следующие настройки: одни worker_process на ядро процессора
:
Worker Processes
1 |
worker_processes = [число ядер процессора]; |
Чтобы определить сколько ядер имеет ваш процессор, введите:
1 2 3 4 5 |
$ cat /proc/cpuinfo | grep processor processor : 0 processor : 1 processor : 2 processor : 3 |
В данном случае у меня четыре ядра, поэтому окончательный парамерт worker_processes
устанавливаем как 4:
1 |
worker_processes = 4; |
Worker Connections
Лично я придерживаюсь 1024 соединений на один воркер, потому что у меня нет никаких оснований для повышения этого значения. Но если например 4096 соединений в секунду не хватает, то можно попробовать удвоить 2048 соединений на процесс.
Окончательные настройки выглядят седующим образом:
1 |
worker_connections 1024; |
Совет №3 — Скрыть токены Nginx / Скрыть номер версии Nginx
Это хорошо из соображений безопасности — скрыть токены Nginx и скрыть номер версии Nginx, тем более если вы используете устаревшую версию Nginx. Это очень легко сделать — достаточно добавить в секцию http/server/location
файла конфигурации следующую строку:
1 |
server_tokens off; |
Совет №4 — Ограничение на размер передаваемых данных сервером Nginx
Если вы хотите разрешить пользователям загружать файлы, то вы должны увеличить размер сообщения. Это может быть сделано с помощью значения client_max_body_size
, которое находится в секции http/server/location
файла конфигурации. По умолчанию он равен 1 Мб, но его можно увеличить, например, до 20 Мб, а также увеличить размер буфера:
1 2 |
client_max_body_size 20m; client_body_buffer_size 128k; |
Если вы получаете сообщение об ошибке, то вы знаете, что client_max_body_size
слишком мало:
«Request Entity Too Large» (413)
Совет №5 — Управление кешем для статических файлов
Кэш браузера сохранит ресурсы и пропускную способность вашего сервера. Это несложная настройка Nginx позволит выключить ведение логов (access log
и not found log
), и установить срок истечения заголовка в 360 дней.
1 2 3 4 5 |
location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ { access_log off; log_not_found off; expires 360d; } |
Если вы хотите более сложный заголовки или другие типы файлов, то вы можете настроить их отдельно.
Совет №6 — Проксируйте PHP запросы к PHP-FPM
Вы можете использовать по умолчанию стек tcp/ip
или соединение через Unix-сокет. Также необходимо установить PHP-FPM слушать точно такой же ip:port
или Unix-сокет. Вот очень простой пример конфигурации (вариант с Unix-сокетом закоментирован):
1 2 3 4 5 6 7 8 9 |
# Pass PHP scripts to PHP-FPM location ~* \.php$ { fastcgi_index index.php; fastcgi_pass 127.0.0.1:9000; #fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; } |
Это дает возможность запуска PHP-FPM другим сервером.
Совет №7 — Предотвращение (запрет) доступа к скрытым файлам
Это очень распространено, когда корень сервера или другие публичные каталоги имеют скрытые файлы, которые начинаются с точки (.) И, как правило, они не предназначены для пользователей сайта. Публичный каталог может содержать файлы системы контроля версий: .git
, .svn
; файлы IDE: .idea
; .htaccess
файлы. Настройки запещают доступ к скрытым файлам и отключают ведение логов:
1 2 3 4 5 |
location ~ /\. { access_log off; log_not_found off; deny all; } |
Советы по настройке и оптимизации PHP-FPM
Совет №1 — Файлы конфигурации PHP-FPM
Обычно конфигурации PHP-FPM расположенны в файле /etc/php-fpm.conf
и в каталоге /etc/php-fpm.d/
. Весь пулл конфигов расопложен в дикертории /etc/php-fpm.d/
. Чтобы это работало, вы должны добавить следующую строку в php-fpm.conf
:
1 |
include=/etc/php-fpm.d/*.conf |
Совет №2 — Глобальная конфигурация PHP-FPM
Настройки emergency_restart_threshold
, emergency_restart_interval
и process_control_timeout
по умолчанию выключены, но я считаю что их стоит влючить, например, со следующими значениями:
1 2 3 |
emergency_restart_threshold 10 emergency_restart_interval 1m process_control_timeout 10s |
Что это значит? Если 10 дочерних процессов PHP-FPM завершатся с помощью SIGSEGV или SIGBUS в течении 1 минуты, то PHP-FPM перезагрузится автоматически. А также дочерним процессам установлен лимит времени реакции в 10 секунд на сигнал от мастера.
Совет №3 — Конфигурация пулов PHP-FPM
В PHP-FPM возможно использовать отденьные пулы для каждого сайта и точно распределять ресурсы, а также использовать разных пользователей и разные группы для каждого пула. Приведем примеры конфигураци трех различнх сайтов (или фактически три части одного сайта):
/etc/php-fpm.d/site.conf
/etc/php-fpm.d/blog.conf
/etc/php-fpm.d/forums.conf
Примеры конфигурации каждого пула:
/etc/php-fpm.d/site.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[site] listen = 127.0.0.1:9000 user = site group = site request_slowlog_timeout = 5s slowlog = /var/log/php-fpm/slowlog-site.log listen.allowed_clients = 127.0.0.1 pm = dynamic pm.max_children = 5 pm.start_servers = 3 pm.min_spare_servers = 2 pm.max_spare_servers = 4 pm.max_requests = 200 listen.backlog = -1 pm.status_path = /status request_terminate_timeout = 120s rlimit_files = 131072 rlimit_core = unlimited catch_workers_output = yes env[HOSTNAME] = $HOSTNAME env[TMP] = /tmp env[TMPDIR] = /tmp env[TEMP] = /tmp |
/etc/php-fpm.d/blog.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[blog] listen = 127.0.0.1:9001 user = blog group = blog request_slowlog_timeout = 5s slowlog = /var/log/php-fpm/slowlog-blog.log listen.allowed_clients = 127.0.0.1 pm = dynamic pm.max_children = 4 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3 pm.max_requests = 200 listen.backlog = -1 pm.status_path = /status request_terminate_timeout = 120s rlimit_files = 131072 rlimit_core = unlimited catch_workers_output = yes env[HOSTNAME] = $HOSTNAME env[TMP] = /tmp env[TMPDIR] = /tmp env[TEMP] = /tmp |
/etc/php-fpm.d/forums.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[forums] listen = 127.0.0.1:9002 user = forums group = forums request_slowlog_timeout = 5s slowlog = /var/log/php-fpm/slowlog-forums.log listen.allowed_clients = 127.0.0.1 pm = dynamic pm.max_children = 10 pm.start_servers = 3 pm.min_spare_servers = 2 pm.max_spare_servers = 4 pm.max_requests = 400 listen.backlog = -1 pm.status_path = /status request_terminate_timeout = 120s rlimit_files = 131072 rlimit_core = unlimited catch_workers_output = yes env[HOSTNAME] = $HOSTNAME env[TMP] = /tmp env[TMPDIR] = /tmp env[TEMP] = /tmp |
Это просто примеры как настроить несколько различных пулов.
Совет №4 — Конфигурация менеджера процессов (Pool Process Manager) PHP-FPM
Лучший способ использовать менеджер процессов PHP-FPM — это донамическое управление процессами, поэтому PHP-FPM запускает процессы только при необходимости. Это почти такой же подход как в Nginx с параметрами worker_processes
и worker_connections
. Таким образом большие значения не обеспечивают хорошего результата. Каждый процесс ест определнное количество памяти и, конечно, если у сайта очень большой трафик и много оперативной памяти на сервере, то высокие значения — это правильный выбор. Но такие серверы как VPS обычно имеют ограниченное количество памяти: 256 Мб, 512 Мб, 1024 Мб. Такого небольшого объема ОЗУ достаточно даже для очень большого трафика (даже десятки запросов в секунду), если эту память использовать с умом.
Проверим сколько процессов PHP-FPM позволит легко справляться серверу с нагрузкой. Сначала запустим Nginx и PHP-FPM и загрузим несколько страниц PHP, желательно самые тяжелые. Затем проверим сколько использует памяти процесс PHP-FPM — в Linux можно воспользоваться утилитами top
или htop
. Предположим что наш сервер имеет 512 Мб оперативной памяти и 220 Мб может быть использованно PHP-FPM, каждый процесс использует 24 Мб оператичной памяти (некоторые CMS с плагинами могут легко кушать 20-40 Мб на один запрос или даже больше). Затем просто вычислим значние max_children
для сервера:
220 / 24 = 9.17
Приемлемым значнием pm.max_children
будет 9. Это значние основанно на среднем значении и возможно далее его необходимо будет изменить, когда вы заметите длительное время использования памяти процессом. После быстрого тестирования несложно выбрать значния pm.start_servers value
, pm.min_spare_servers
и pm.max_spare_servers
.
Окончательная конфигурация нашего примера может выглядеть следующим образом:
1 2 3 4 5 |
pm.max_children = 9 pm.start_servers = 3 pm.min_spare_servers = 2 pm.max_spare_servers = 4 pm.max_requests = 200 |
Максималоное количество запросов на процесс по умолчанию не ограничено, но хорошо бы установить какое-нибудь небольшое значение, например 200, и избежать проблем с памятью. Такого вида настрока может обрабарывать большое количество запросов, даже если значение параметра невелико.
У вас проблемы с натройкой Nginx или PHP-FPM или есть еще советы?
Не стесняйтеся писать замечания, вопросы и советы в комментариях.