Классический режим
Классический режим выполняет обычный фронт-контроллер на PHP — тот самый public/index.php, на который вы уже направили php-fpm, — с нуля на каждый пришедший запрос. Rapira встаёт на место php-fpm, и приложение не требует изменений: суперглобальные переменные заполнены, скрипт отрабатывает сверху вниз, и всё, что он напечатал, становится ответом.
Чистое состояние на каждый запрос
Каждый запрос проходит полный цикл PHP: старт запроса, ваш входной скрипт, завершение запроса. Всё, что скрипт успел построить по дороге — глобальные переменные, статические свойства, DI-контейнер, карту объектов ORM, — разбирается до начала следующего запроса, ровно как под php-fpm.
Утёкший дескриптор, синглтон, инициализированный наполовину, библиотека, которая прячет данные запроса в статическом свойстве, — ничто из этого не влияет на следующий запрос, ведь созданное скриптом не переживает тот запрос, в котором было создано. Исключения ровно те же, что и у php-fpm: постоянные соединения и состояние внутри расширений живут в процессе воркера, а не в запросе. Код, который не рассчитан на долгоживущий процесс, работает здесь без изменений. Функция fastcgi_finish_request() приходит из бинарника php-fpm, и в Rapira её нет; вместо неё есть rapira_finish_request() с тем же контрактом — отдать ответ клиенту раньше времени и продолжить работу после этого, — она описана в разделе HTTP.
Приложение поднимается заново на каждый запрос: автозагрузчик, конфиг, контейнер, маршруты. Подробнее — в разделе Режимы выполнения.
Как включить
Выбрать режим можно двумя способами, и делают они одно и то же:
--classicв командной строке, рядом с входным скриптом.classic = trueв секции[pool]файлаrapira.toml.
Флаг умеет только включать режим: --no-classic не существует, поэтому конфиг с classic = true останется классическим, что бы ни было в командной строке. В остальном действует обычный порядок: флаги сильнее файла конфигурации. Полный список ключей — в Конфигурации.
Входной скрипт для классического режима — это обычный PHP:
<?php
// index.php
header('Content-Type: text/plain');
echo "Hello, " . ($_GET['name'] ?? 'anonymous') . "!\n";
echo "Method: {$_SERVER['REQUEST_METHOD']}\n";Направьте на него Rapira любым из двух способов:
rapira serve --classic public/index.php[pool]
entrypoint = "public/index.php"
classic = trueС файлом конфигурации команда запуска выглядит так: rapira serve --config rapira.toml. Относительный pool.entrypoint считается от каталога самого файла конфигурации, поэтому конфиг можно спокойно переносить; а относительный путь к скрипту в командной строке считается от текущего каталога. Про остальные опции рассказывает Командная строка.
Входной скрипт
Rapira не сопоставляет URL с файлами на диске и сама по себе с диска ничего не отдаёт. Любой запрос, с каким бы путём он ни пришёл, выполняет тот входной скрипт, который вы указали, а сам URL попадает в $_SERVER['REQUEST_URI'] — дальше маршрутизацией занимается приложение.
Отсюда и значения CGI-переменных: SCRIPT_FILENAME — всегда входной скрипт, SCRIPT_NAME — его имя файла со слешем впереди (/index.php), а DOCUMENT_ROOT — каталог, в котором он лежит. Статику придётся отдавать чем-то, что стоит перед Rapira: сетью доставки контента или обратным прокси, настройку которого разбирает Запуск в продакшене.
OPcache
Выполнение с нуля сбрасывает состояние вашего приложения, но не скомпилированный байт-код. Мастер-процесс запускает PHP ровно один раз, на старте модуля, ещё до того, как форкнет первого воркера, поэтому OPcache создаёт свой сегмент разделяемой памяти единственный раз, и каждый форкнутый воркер наследует то же самое отображение. С включённым OPcache скомпилированные скрипты остаются в кеше и между запросами, и сразу на весь пул: выполнить фронт-контроллер заново не значит заново его разобрать.
Сам пул процессов в обоих режимах одинаковый: мастер форкает воркеров, каждый воркер обрабатывает по одному запросу за раз, а параллельность даёт количество процессов. Подробнее о мастер-процессе и его воркерах рассказывает Модель процессов.
В классическом режиме Rapira\create_plugin_handler() бросает Rapira\RapiraException: обработчики плагинов работают только в режиме воркера. Отдавать обработчик просто некуда — резидентного цикла нет, скрипт заканчивается вместе с запросом. Скриптам воркера место в режиме SAPI Worker.
Выбор между Classic и SAPI Worker
Используйте классический режим, когда состояние приложения не переживает второй запрос: старая кодовая база, фреймворк, который оставляет состояние в статических свойствах, чужая библиотека, которую вы не контролируете, — или когда вы уходите с php-fpm и хотите менять по одной вещи за раз. Используйте режим SAPI Worker, когда код выдерживает процесс, который не завершается, и вы хотите убрать загрузку приложения на каждом запросе. Все четыре режима описывает Режимы выполнения; из них сегодня готовы Classic и SAPI Worker.