nginx

Советы по настройке и оптимизации Nginx и PHP-FPM

От переводчика:
Речь пойдет о тонкостях настройки связки Nginx + PHP-FPM в виде небольшого сборника советов. Перевод вольный. Ориентированно на пользователей Linux.

Советы по настройке и оптимизации Nginx

Совет №1 — Организация файлов конфигурации Nginx

Обычно файлы конфигурации Nginx хранятся в /etc/nginx.

Один из удобных способов организации файлов конфигурации в стиле Debian/Ubuntu Apache:

Файлы виртуальных хостов разделены на две директории. Директория sites-available может содержать любые файлы: тестовые, старые конфиги, копии конфигов и прочие. А директория sites-enabled содержит только реально работающие конфигурации, в действительности являющиеся только символическими ссылками на файлы в директории sites-available.

Не забудьте добавить следующие строки в файл nginx.conf:

Совет №2 — Определить Nginx worker_processes и worker_connections

Настройки по умолчанию  хороши, но их стоит немного оптимизировать: max_clients = worker_processes * worker_connections.

Базовые настройки Nginx могут обрабатывать сотни одновременных соединений:

Обычно 1000 одновременных соединений на один сервер это хорошо, но порою другие части, например жесткий диск могут оказаться медленными и это приведет к тому, что Nginx будет заблокирован на операции ввода-вывода (I/O). Чтобы избежать блокировки используйте, например, следующие настройки: одни worker_process на ядро процессора:

Worker Processes

Чтобы определить сколько ядер имеет ваш процессор, введите:

В данном случае у меня четыре ядра, поэтому окончательный парамерт worker_processes устанавливаем как 4:

Worker Connections

Лично я придерживаюсь 1024 соединений на один воркер, потому что у меня нет никаких оснований для повышения этого значения. Но если например 4096 соединений в секунду не хватает, то можно попробовать удвоить 2048 соединений на процесс.

Окончательные настройки выглядят седующим образом:

Совет №3 — Скрыть токены Nginx / Скрыть номер версии Nginx

Это хорошо из соображений безопасности — скрыть токены Nginx и скрыть номер версии Nginx, тем более если вы используете устаревшую версию Nginx. Это очень легко сделать — достаточно добавить в секцию http/server/location файла конфигурации следующую строку:

Совет №4 — Ограничение на размер передаваемых данных сервером Nginx

Если вы хотите разрешить пользователям загружать файлы, то вы должны увеличить размер сообщения. Это может быть сделано с помощью значения client_max_body_size, которое находится в секции http/server/location файла конфигурации. По умолчанию он равен 1 Мб, но его можно увеличить, например, до 20 Мб, а также увеличить размер буфера:

Если вы получаете сообщение об ошибке, то вы знаете, что client_max_body_size слишком мало:

«Request Entity Too Large» (413)

Совет №5 — Управление кешем для статических файлов

Кэш браузера сохранит ресурсы и пропускную способность вашего сервера. Это несложная настройка Nginx позволит выключить ведение логов (access log и not found log), и установить срок истечения заголовка в 360 дней.

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

Совет №6 — Проксируйте PHP запросы к PHP-FPM

Вы можете использовать по умолчанию стек tcp/ip или соединение через Unix-сокет. Также необходимо установить PHP-FPM слушать точно такой же ip:port или Unix-сокет. Вот очень простой пример конфигурации (вариант с Unix-сокетом  закоментирован):

Это дает возможность запуска PHP-FPM другим сервером.

Совет №7 — Предотвращение (запрет) доступа к скрытым файлам

Это очень распространено, когда корень сервера или другие публичные каталоги имеют скрытые файлы, которые начинаются с точки (.) И, как правило, они не предназначены для пользователей сайта. Публичный каталог может содержать файлы системы контроля версий: .git, .svn; файлы IDE: .idea; .htaccess файлы. Настройки запещают доступ к скрытым файлам и отключают ведение логов:

 Советы по настройке и оптимизации PHP-FPM

Совет №1 — Файлы конфигурации PHP-FPM

Обычно конфигурации PHP-FPM расположенны в файле /etc/php-fpm.conf и в каталоге /etc/php-fpm.d/. Весь пулл конфигов расопложен в дикертории /etc/php-fpm.d/. Чтобы это работало, вы должны добавить следующую строку в php-fpm.conf:

Совет №2 — Глобальная конфигурация PHP-FPM

Настройки emergency_restart_thresholdemergency_restart_interval и process_control_timeout по умолчанию выключены, но я считаю что их стоит влючить, например, со следующими значениями:

Что это значит? Если 10 дочерних процессов PHP-FPM завршатся с помощью SIGSEGV или SIGBUS, то PHP-FPM перезагрузится через 1 минуту. А также дочерним процессам  установлен лимит времени реакции в 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

/etc/php-fpm.d/blog.conf

/etc/php-fpm.d/forums.conf

Это просто примеры как настроить несколько различных пулов.

Совет №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.

Окончательная конфигурация нашего примера может выглядеть следующим образом:

Максималоное количество запросов на процесс по умолчанию не ограничено, но хорошо бы установить какое-нибудь небольшое значение, например 200, и избежать проблем с памятью. Такого вида настрока может обрабарывать большое количество запросов, даже если значение параметра невелико.

У вас проблемы с натройкой Nginx или PHP-FPM или есть еще советы?

Не стесняйтеся писать замечания, вопросы и советы в комментариях.

Оригинальный пост на английском языке

  • cat /proc/cpuinfo | grep processor зачем так сложно nproc и сразу число

  • Evgeny

    у меня на VDS
    [root@e php-fpm.d]# nproc
    24
    [root@e php-fpm.d]# cat /proc/cpuinfo | grep processor
    processor : 0
    processor : 1
    processor : 2
    processor : 3

    • $ man nproc

      nproc — print the number of processing units available

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

  • Алексей

    Столкнулся с проблемой настройки конфига для сайтов в папках. CMS — WordPress, в каталоге несколько папок, в каждой из которых отдельный сайт. http://мойсайт.ru, http://мойсайт.ru/site1, http://мойсайт.ru/site2 и.т.д Имеется стандартное решение на этот случай?

    • Есть нескольто рекомендиций по настройке nginx для wordpress: https://codex.wordpress.org/Nginx#WordPress_Multisite_Subdirectory_rules. Я не знаю насколько актуальный этот пост, но рекомендовал бы посматривать в оф.документацию nginx. а также использовать актуальную стабильную версию nginx 1.8.

    • Alexandr Klokov

      А по поводу настроек в статье — в принципе неплохо описано, но есть нюансы. Я рекомендую настраивать php-fpm в режиме ondemand. Рекомендуемый автором dynamic самый непроизводительный. Самый быстрый static, но тут нужно знать сколько процессов (pm.max_childrens ) для вашеих ресурсов будет допустимо. Ondemand — запускает процессы при необходимости и завершает их, когда нет нагрузки. У dynamic сложности с высвобождением ресурсов, static же хоть и самый производительный, но самый требовательный к ресурсам.

      • К сожалению ссылка небезопасна и я не могу апрувить этот коммент без редакции.

        • Alexandr Klokov

          Это которая ссылка?

  • Обновил на сервере nginx с 0.7.67 до версии 1.8. Не обошлось без мелких неприятностей, связанных с настройками. Поделитесь грамотно настроенным конфигом под версию 1.8 для максимальной производительности.

    • Нет универсальных решений, постоянно приходится подстраиваться под конкретные задачи, но для начала рекомендую обратить внимание на (пример для PHP):

      1. Заготовку https://github.com/h5bp/server-configs-nginx

      2. Если нужен PHP — FastCGI через Unix-сокет (http://nginx.org/ru/docs/http/ngx_http_fastcgi_module.html)

      3. Для красивых URL примерно:
      location / {
      try_files $uri $uri/ /index.php?$query_string;
      }

      В остальном принципы не изменились: оптимизируйте под железо, кэшируйте статику, сжимайте трафик, следили за приватностью важных данных…

      p.s.: Используйте SSL!

  • DANic

    из-за request_slowlog_timeout в error лог появляется:

    failed to ptrace(PEEKDATA) pid 2322: Input/output error (5)
    рекомендуют отключить эту настройка так ка кот нее бывает проблем больше чем пользы

    worker_processes

    Оптимальное значение зависит от множества факторов, включая (но не ограничиваясь ими) число процессорных ядер, число жёстких дисков с данными и картину нагрузок. Если затрудняетесь в выборе правильного значения, можно начать с установки его равным числу процессорных ядер (значение “auto” пытается определить его автоматически).(из документации)
    Так же встречал что в последних версиях nginx хорошо работает значение auto

  • Denis Ilichev

    Спасибо! Эта статья помогла разобраться с Out of memory в логах php-fpm

  • Марк Гольцев

    Оптимальные настройки бы для дедика 32 гига оперативы увидеть хоть раз:)