Оптимизация php для symfony

Symfony - это еще один фреймворк для разработки веб-приложений на языке PHP. Так как он написан на php, то я разберу основные настройки php для большей скорости работы.
Настройки будут для php8-fpm.

В нашем примере PgSQL\Redis\memcached вынесены на другую ВМ. В нашей ВМ CPU 4, RAM 8Gb.

Так как мы пока не знаем, сколько будет пользователй онлайн в единицу времени, будем отталкиваться от 50 слушателей для fpm. Созданим новый файл настройки для fpm


; Имя пула. Можно создать несколько для разных задач.

[symfony_prod]

; Использовать Unix-сокет - меньше накладных расходов, чем TCP

listen = /run/php/php8.x-fpm-symfony.sock

listen.owner = www-data

listen.group = www-data

listen.mode = 0660

; Статический менеджер процессов - дает максимальную производительность,

; так как все процессы создаются заранее и готовы к работе.

; Платим памятью, но на 8 GB это оправдано.

pm = static

; Ключевой параметр! Рассчитываем количество воркеров.

; 1. Средний размер одного воркера Symfony (с предзагрузкой) ~ 40-80MB.

; 2. Выделяем 6 GB под PHP (оставляем 2 GB для ОС, кешей, Nginx и т.д.).

; 3. 6144MB / 70MB ~ 88.

; Берем с запасом, учитывая пиковые нагрузки. Начинаем с 50.

pm.max_children = 50

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

; После обработки 1000 запросов воркер будет перезапущен.

pm.max_requests = 1000

; Приоритет процесса. Можно немного повысить, но осторожно.

; pm.priority = 0

; Безопасность и производительность

security.limit_extensions = .php .php8

; Важно для избежания блокировки при высоких нагрузках

php_admin_value[disable_functions] = exec,passthru,shell_exec,system

php_admin_flag[allow_url_fopen] = off

php_admin_flag[short_open_tag] = off

; Логирование только критичных ошибок чтобы избежать затрат на I/O

php_admin_value[error_log] = /var/log/php/symfony-prod.log

php_admin_value[log_level] = error

; Устанавливаем корректный umask для файлов, создаваемых PHP

php_admin_value[umask] = 0022

; Защита от переполнения памяти в одном скрипте

php_admin_value[memory_limit] = 256M

OPcache - это необходимость, которая включана по умолчанию, но еще не настроена, эти параметры мы настроим в opcache.ini, обычно это в /etc/php/8.x/fpm/conf.d/10-opcache.ini


zend_extension=opcache.so

; Агрессивные настройки для продакшена

opcache.enable=1

opcache.enable_cli=0 ; Для FPM не нужно

opcache.memory_consumption=512 ; Выделяем 512MB под кеш OPcache! Этого хватит для очень большого проекта.

opcache.interned_strings_buffer=32 ; Больше повторяющихся строк в памяти - меньше её расход.

opcache.max_accelerated_files=30000 ; Современные фреймворки содержат ОЧЕНЬ много файлов.

opcache.validate_timestamps=0 ; ВКЛЮЧАЕМ НА ПРОДАКШЕНЕ! Таймстампы проверяться не будут. Скорость максимальна.

; ВАЖНО: При validate_timestamps=0 кеш НЕ будет обновляться при изменении файлов.

; Очистку кеша (через php-fpm restart или opcache_reset()) нужно делать при каждом деплое автоматически.

opcache.revalidate_freq=0

opcache.fast_shutdown=1

opcache.file_update_protection=0

; Preloading - САМАЯ важная настройка для Symfony

opcache.preload=/var/www/symfony/var/cache/prod/App_KernelProdContainer.preload.php

opcache.preload_user=www-data

; Настройки JIT. Режим tracing лучше всего подходит для сложных приложений.
; Выделяем 256M под буфер JIT. На 4 CPU это хорошее значение.

opcache.jit_buffer_size=256M

opcache.jit=1255 ; Алиас для "tracing" режима с максимальным уровнем оптимизации
; Расшифровка 1255: 1 (CPU-specific optimization) | 2 (enable JIT) | 55 (tracing JIT)
; Альтернативно, можно использовать opcache.jit=tracing

Настроим само приложение на symfony, в нём есть .env.prod (.env.local)


APP_DEBUG=0

APP_ENV=prod

Далее сделаем предзагрузку в самой симфони и прочистим кеши


composer install --no-dev --optimize-autoloader --classmap-authoritative --apcu-autoloader

php bin/console cache:clear --env=prod --no-debug

php bin/console cache:warmup --env=prod --no-debug

Флаг --classmap-authoritative создает идеальный автозагрузчик класса, а --apcu-autoloader кеширует его находки в APCu, что еще больше ускоряет автозагрузку.

Убедитесь, что файл var/cache/prod/App_KernelProdContainer.preload.php существует после кеширования. Путь к нему нужно указать в opcache.preload.

Все проекты разные и разные настройки нужны. Вот пример команды, что бы узнать сколько памяти потребляет процес php


# Узнаем средний размер памяти на воркер (RSS)

ps --user www-data -o rss,comm | grep php-fpm | awk '{sum+=$1} END {printf "Средний размер воркера: %.2f MB\n", sum/NR/1024}'

# Расчет: (Общая память - Память под ОС, БД и пр.) / Размер одного воркера

# Пример: (8192 - 2048) / 70 = ~88 воркеров (это теоретический максимум, мы начали с 50).

 

bitrix24 + nginx + php-fpm

Битрикс шмитрикс, та еще головная боль. Но бизнес требует что бы проект был на битриксе, а ставить их битриксвм у …

Корпоративный почтовый сервер на минималках (postfix + dovecot + freeipa)

Postfix — агент передачи почты (MTA — mail transfer agent). Postfix является свободным программным обеспечением, создавался как альтернатива Sendmail.
Изначально Postfix …

Настрока фаервола nftables

nftables — подсистема ядра Linux, обеспечивающая фильтрацию и классификацию сетевых пакетов/датаграмм/кадров. Включена в ядро Linux, начиная с версии 3.13, выпущенной …

PostgreSQL master slave репликация