Octane запускає Laravel у довгоживучих процесах (FrankenPHP, Swoole, RoadRunner): застосунок завантажується один раз, а потім обробляє тисячі запитів. Бутстрап фреймворку зникає з кожного запиту - час відповіді падає в рази.
FROM dunglas/frankenphp:1-php8.5
# ...
CMD ["php", "artisan", "octane:frankenphp", "--host=0.0.0.0", "--port=8000", "--workers=4", "--max-requests=500"]
Що змінюється для контейнера:
1. Пам'ять:
- кожен воркер тримає завантажений застосунок - сотні МБ на кілька воркерів;
--workers(за замовчуванням - за кількістю ядер) треба узгоджувати з лімітом пам'яті контейнера, інакше OOM-killer з кодом 137;- кількість ядер, яку бачить PHP, - це ядра хоста, а не ліміт
--cpusконтейнера. Явно задавайте--workers.
2. Витоки пам'яті й стан:
- пам'ять, що «протікає» за запит, накопичується;
--max-requests- воркер перезапускається після N запитів і звільняє пам'ять;- стан між запитами: статичні властивості, синглтони, що зберігають запит чи користувача, масиви-кеші в сервісах - переживають запит. Дані одного користувача можуть потрапити до іншого;
- в Octane застосунок клонує контейнер на кожен запит, але синглтони, створені при старті, спільні - не інжектуйте
Request,Authчи конфігурацію в конструктор синглтона.
3. Деплой:
- новий код - новий образ і новий контейнер, тож
octane:reloadдля продакшену в Docker зазвичай не потрібен; --watch- лише для розробки (потребує Node і chokidar), у продакшен-образ не потрапляє;- коректна зупинка: SIGTERM до Octane,
stop_grace_periodбільший за найдовший запит.
4. Конфігурація:
config:cacheпри старті до запуску Octane - конфігурація завантажується один раз і далі не перечитується;- зміна змінних оточення вимагає перезапуску контейнера.
5. З'єднання:
- з'єднання з базою й Redis живуть між запитами - після перезапуску бази перший запит може отримати «server has gone away»; Laravel перепідключається, але варто перевірити поведінку;
- кількість з'єднань з базою = кількість воркерів × реплік - узгоджуйте з
max_connectionsчи пулером.
Що перевірити перед переходом: тести під Octane, пакети на сумісність, навантажувальний тест з контролем пам'яті в docker stats протягом тривалого часу.