Эта страница была переведена сообществом и не обязательно является актуальной. Обратитесь к справочной версии.
Эта страница была переведена сообществом и не обязательно является актуальной. Обратитесь к справочной версии.
Эта страница была переведена сообществом и не обязательно является актуальной. Обратитесь к справочной версии.
По умолчанию FrankenPHP стремится предложить хороший компромисс между производительностью и простотой использования. Однако, используя подходящую конфигурацию, можно существенно улучшить производительность.
По умолчанию FrankenPHP запускает в 2 раза больше потоков и воркеров (в режиме воркера), чем доступное количество ядер процессора.
Подходящие значения сильно зависят от того, как написано ваше приложение, что оно делает, и от вашего оборудования. Мы настоятельно рекомендуем изменить эти значения. Для лучшей стабильности системы рекомендуется, чтобы num_threads x memory_limit < available_memory.
Чтобы найти подходящие значения, лучше всего провести нагрузочные тесты, имитирующие реальный трафик. k6 и Gatling являются хорошими инструментами для этого.
Чтобы настроить количество потоков, используйте опцию num_threads директив php_server и php. Для изменения количества воркеров используйте опцию num секции worker директивы frankenphp.
max_threadsХотя всегда лучше точно знать, как будет выглядеть ваш трафик, реальные приложения, как правило, более непредсказуемы. Конфигурация max_threads позволяет FrankenPHP автоматически создавать дополнительные потоки во время выполнения до указанного предела. max_threads может помочь вам определить, сколько потоков требуется для обработки вашего трафика, и может сделать сервер более устойчивым к скачкам задержки. Если установлено значение auto, лимит будет оценен на основе memory_limit в вашем php.ini. Если это невозможно, auto вместо этого будет по умолчанию равно 2x num_threads. Имейте в виду, что auto может сильно недооценивать необходимое количество потоков. max_threads похожа на pm.max_children в PHP FPM. Основное отличие состоит в том, что FrankenPHP использует потоки вместо процессов и автоматически распределяет их между различными скриптами воркеров и ‘классическим режимом’ по мере необходимости.
Включение режима воркера значительно улучшает производительность, но ваше приложение должно быть адаптировано для совместимости с этим режимом: необходимо создать скрипт воркера и убедиться, что приложение не имеет утечек памяти.
Вариант официальных Docker-образов для Alpine Linux и предоставляемые нами бинарные файлы по умолчанию используют библиотеку musl libc.
Известно, что PHP работает медленнее при использовании этой альтернативной библиотеки C вместо традиционной библиотеки GNU, особенно при компиляции в режиме ZTS (потокобезопасном режиме), который требуется для FrankenPHP. Разница может быть существенной в сильно многопоточной среде.
Кроме того, некоторые ошибки проявляются исключительно при использовании musl.
В производственных средах мы рекомендуем использовать FrankenPHP, скомпилированный с glibc и с соответствующим уровнем оптимизации.
Этого можно достичь, используя Docker-образы Debian, используя пакеты .deb, .rpm или .apk от наших мейнтейнеров или компилируя FrankenPHP из исходников.
Для более компактных или безопасных контейнеров вы можете рассмотреть усиленный образ Debian вместо Alpine.
FrankenPHP написан на языке Go.
В целом, среда выполнения Go не требует какой-либо особой настройки, но при определенных обстоятельствах специфическая конфигурация улучшает производительность.
Вероятно, вы захотите установить переменную окружения GODEBUG в значение cgocheck=0 (по умолчанию в Docker-образах FrankenPHP).
Если вы запускаете FrankenPHP в контейнерах (Docker, Kubernetes, LXC…) и ограничиваете память, доступную для контейнеров, установите переменную окружения GOMEMLIMIT в значение доступного объёма памяти.
Для получения более подробной информации страница документации Go, посвященная этой теме, обязательна к прочтению, чтобы максимально эффективно использовать среду выполнения.
file_serverПо умолчанию директива php_server автоматически настраивает файловый сервер для обслуживания статических файлов (ресурсов), хранящихся в корневой директории.
Эта функция удобна, но имеет издержки. Чтобы отключить её, используйте следующую конфигурацию:
php_server {
file_server off
}
try_filesПомимо статических файлов и файлов PHP, php_server также попытается обслужить индекс вашего приложения и индексные файлы директорий (/path/ -> /path/index.php). Если вам не нужны индексы директорий, вы можете отключить их, явно определив try_files следующим образом:
php_server {
try_files {path} index.php
root /root/to/your/app # явное указание корневой директории здесь обеспечивает лучшее кеширование
}
Это может значительно сократить количество ненужных файловых операций. Эквивалент предыдущей конфигурации для воркера будет следующим:
route {
php_server { # используйте "php" вместо "php_server", если вам вообще не нужен файловый сервер
root /root/to/your/app
worker /path/to/worker.php {
match * # отправить все запросы напрямую воркеру
}
}
}
Альтернативный подход с 0 ненужных операций файловой системы заключается в использовании директивы php и разделении файлов от PHP по пути. Этот подход хорошо работает, если все ваше приложение обслуживается одним входным файлом. Пример конфигурации, которая обслуживает статические файлы за папкой /assets, может выглядеть так:
route {
@assets {
path /assets/*
}
# всё, что находится за /assets, обрабатывается файловым сервером
file_server @assets {
root /root/to/your/app
}
# всё, что не находится в /assets, обрабатывается вашим индексным или воркер PHP-файлом
rewrite index.php
php {
root /root/to/your/app # явное указание корневой директории здесь обеспечивает лучшее кеширование
}
}
Вы можете использовать плейсхолдеры в директивах root и env. Однако это предотвращает кеширование значений и существенно снижает производительность.
По возможности избегайте использования плейсхолдеров в этих директивах.
resolve_root_symlinkПо умолчанию, если корневая директория документа является символьной ссылкой, она автоматически разрешается FrankenPHP (это необходимо для корректной работы PHP). Если корневая директория документа не является символьной ссылкой, вы можете отключить эту функцию.
php_server {
resolve_root_symlink false
}
Это улучшит производительность, если директива root содержит плейсхолдеры. В остальных случаях прирост производительности будет минимальным.
Логирование, безусловно, очень полезно, но, по определению, оно требует операций ввода-вывода и выделения памяти, что значительно снижает производительность. Убедитесь, что вы правильно настроили уровень логирования и логируете только то, что необходимо.
FrankenPHP использует официальный интерпретатор PHP. Все обычные оптимизации производительности, связанные с PHP, применимы к FrankenPHP.
В частности:
realpath достаточно велик для нужд вашего приложения;Для получения более подробной информации ознакомьтесь с разделом документации Symfony, посвященным производительности (большинство советов полезны, даже если вы не используете Symfony).
Приложениям часто приходится взаимодействовать с медленными внешними службами, такими как API, который имеет тенденцию быть ненадежным при высокой нагрузке или постоянно отвечает в течение 10+ секунд. В таких случаях может быть полезно разделить пул потоков, чтобы иметь выделенные “медленные” пулы. Это предотвращает потребление медленными конечными точками всех ресурсов/потоков сервера и ограничивает параллелизм запросов, направляемых к медленной конечной точке, подобно пулу соединений.
example.com {
php_server {
root /app/public # корень вашего приложения
worker index.php {
match /slow-endpoint/* # все запросы к /slow-endpoint/* обрабатываются этим пулом потоков
num 1 # минимум 1 поток для запросов к /slow-endpoint/*
max_threads 20 # при необходимости разрешить до 20 потоков для запросов к /slow-endpoint/*
}
worker index.php {
match * # все остальные запросы обрабатываются отдельно
num 1 # минимум 1 поток для остальных запросов, даже если медленные конечные точки начинают зависать
max_threads 20 # при необходимости разрешить до 20 потоков для остальных запросов
}
}
}
В целом, также рекомендуется обрабатывать очень медленные конечные точки асинхронно, используя соответствующие механизмы, такие как очереди сообщений.
Редактировать эту страницу