Tuning
Тонкая настройка
Изначально многие серверные приложения поставляются с базовой конфигурацией, которая позволяет их запускать на самых простых и малопроизводительных устройствах. Такие системы нуждаются в обязательной подстройке параметров под те серверы и операционные системы, на которых они используются. Эти действия могут значительно (в разы или десятки раз) повысить утилизацию ресурсов сервера и тем самым значительно повысить производительность системы в целом.
Хотя этот шаг и не является обязательным, мы крайне рекомендуем произвести такую подстройку.
PostgreSQL
Для расчета параметров работы сервера существуют специальные калькуляторы, облегчающие подобные вычисления. Воспользуйтесь одним из калькуляторов для расчета параметров:
Вам нужно указать технические характеристики сервера, версию Postgres и т.д.. На выходе вы получите набор рекомендуемых значений параметров, которые необходимо внести в файл /etc/postgresql/13/main/postgresql.conf и затем перезагрузить PostgreSQL:
sudo systemctl restart postgres
Дополнительную информацию по оптимизации PostgreSQL вы можете узнать в интернет. Например, пр следующим ссылкам:
- https://wiki.postgresql.org/wiki/Performance_Optimization
- https://ruhighload.com/post/%D0%A2%D1%8E%D0%BD%D0%B8%D0%BD%D0%B3+%D0%B1%D0%B0%D0%B7%D1%8B+Postgres
Архитектура файловой системы PostgreSQL рассчитана на быструю работу в ущерб размерам файлов. PostgreSQL не тратит время на попытки обновления данных в том же месте на диске, где находятся эти обновляемые данные. Он просто помечает обновляемые данные как удаленные и добавляет новую запись в файл. Таким образом достигается масимальная производительность системы, но файлы становятся очень фрагментированными. Избавиться от фрагментирования помогает процедура вакуумирования. По умолчанию, после установки PostgreSQL, автоматически добавляется процесс автоматического вакуумирования, который параллельно с работой PostgreSQL следит за состоянием файлов и при отсутствии нагрузки на файловую систему производит низкоприоритетную дефрагментацию. Никогда не отключайте автовакуумирование, иначе файлы базы данных разрастутся до огромных размеров.
Помимо этого вам может быть полезна информация о запуске вакуумирования вручную и о процедуре перестройки индексов. Это операции в некоторых случаях могут значительно ускорить работу базы данных: https://dba.stackexchange.com/questions/135881/postgresql-error-failed-to-re-find-parent-key-in-index
PHP-FPM
По умолчанию за настройку пула отвечает файл /etc/php/7.4/fpm/pool.d/www.conf
Этот файл содержит несколько настроек менеджера процессов (PM), которые начинаются с pm
Мы рекомендуем использовать динамический пул, так как на одном сервере работают и другие службы. В этом случае менеджер процессов будет управлять количеством процессов php-fpm в памяти автоматически, высвобождая ресурсы, если в них нет необходимости. По умолчанию менеджер процессов работает именно в этом режиме, но на всякий случай убедитесь, что это именно так: pm = dynamic
Далее необходимо настроить количество процессов php-fpm, а также остальные настройки. Здесь понадобится произвести некоторые вычисления.
Один процесс php-fpm занимает примерно 48 Мб в ОЗУ (это справедливо только для USERSIDE). Однако, если у вас слишком большой объем данных в USERSIDE, то это значение может быть несколько больше. Главное использовать не максимальное, а среднее значение. Ведь не все до единого запросы потребляют максимальное количество ОЗУ. Чтобы узнать, какое количество ОЗУ потребляют ваши процессы PHP-FPM, то в момент нормальной рабочей нагрузки на WEB-приложение USERSIDE, выполните команду:
ps -eo rss,comm,cmd | grep php-fpm
В результате вы получите вывод, состоящий из трех колонок:
3304 php-fpm7.4 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf) 41596 php-fpm7.4 php-fpm: pool www 36304 php-fpm7.4 php-fpm: pool www 38516 php-fpm7.4 php-fpm: pool www
Здесь виден мастер-процесс PHP-FPM и три воркера - их порождает мастер и именно они обрабатывают WEB-запросы. В данном случае три воркера потребляют в среднем 38 Мб. Запоминаем это значение.
Теперь необходимо узнать, сколько свободной оперативной памяти у нас есть. Делать это необходимо после оптимизации PostgreSQL и желательно в момент нормальной рабочей нагрузки. Выполните:
free -m
В результате вы получите приблизительно следующий вывод:
total used free shared buff/cache available Mem: 996 147 331 124 516 581
Чтобы вычислить объем оперативной памяти, который можно использовать, воспользуемся формулой: available = total - (used + buff). В данном случае это 333 Мб.
Весь этот объем оперативной памяти мы бы могли использовать для пула php-fpm. Но все же желательно взять от него около 80%, не более. В данном случае это примерно 266 Мб.
Теперь считаем количество воркеров. Один воркер потребляет в среднем 38 Мб, а объем свободной памяти 266 Мб. Всё это очень приблизительно, так как эти значения далеко не постоянны. Нам остается просто разделить объем свободной памяти на количество памяти, потребляемой одним воркером. Получим 266 / 38 = 7. Такое максимальное количество воркеров мы можем запустить.
Указываем в качестве значения pm.max_children = 7
.
Далее необходимо настроить минимальное и максимальное количество воркеров, ожидающих соединеия. За это отвечают параметры pm.min_spare_servers
и pm.max_spare_servers
соответственно. Значения этих параметров подбираются "на глаз" и зависят от реального количества запросов, от их "тяжести" и многого другого. Для начала возьмем минимальное количество ожидающих воркеров примерно 25% от общего максимума (max_children), а максимальное примерно 50%.
pm.min_spare_servers = 2 pm.max_spare_servers = 4
Далее необходимо настроить количество воркеров, которое будет запущено при старте пула php-fpm. За это отвечает параметр pm.start_servers
и его значение рассчитывается по формуле: min_spare_servers + (max_spare_servers - min_spare_servers) / 2. В нашем случае, это 3
Итого, настройка менеджера процессов пула PHP-FPM будет следующей:
pm.max_children = 7 pm.min_spare_servers = 2 pm.max_spare_servers = 4 pm.start_servers = 3
Здесь важно отметить следующие моменты. В этих демонстрационных расчетах использовались данные сервера с объемом ОЗУ 1 Гб. В вашем же случае на реальном сервере максимальное количество воркеров может получиться очень большим - несколько сотен. Однако не стоит использовать такое большое количество воркеров, если у вас работает всего два оператора и никто больше не работает с USERSIDE. Лишние воркеры будут просто бесполезно занимать ОЗУ, которое могло быть использовано тем же PostgreSQL в мирных целях. Данные рекомендации помогут понять, какое максимальное количество воркеров можно использовать для максимальной утилизации системы, но если в таком количестве процессов, ожидающих http-запросы, нет смысла, то нет необходимости использовать его - просто понизьте его до разумных значений.
Также рекомендуем наблюдать за файлом журнала php-fpm на предмет проблем с воркерами.
tail -f /var/log/php7.4-fpm.log
Об этом могут говорить строки вроде следующей:
WARNING: [pool www] server reached pm.max_children setting (5), consider raising it