Быстрый старт
Эта страница описывает, как отдать страницу в классическом режиме, превратить то же приложение в резидентный воркер и перенести настройки в файл конфигурации. Предполагается, что у вас уже есть рабочий бинарник rapira и PHP, который идёт с ним в комплекте; подробнее — в разделе Установка.
Классический режим
Классический режим доступен любому приложению: Rapira заново подключает ваш входной скрипт на каждый запрос, ровно так же, как php-fpm выполняет фронт-контроллер. Код при этом менять не нужно.
Создайте public/index.php:
<?php
header('Content-Type: text/plain');
echo "Hello, " . ($_GET['name'] ?? 'anonymous') . "!\n";
echo "Method: {$_SERVER['REQUEST_METHOD']}\n";Теперь запустите сервер. Флаг --classic выбирает режим, а входной скрипт передаётся позиционным аргументом:
rapira serve --classic public/index.phpЕсли не сказать иначе, Rapira слушает 127.0.0.1:8000. Из другого терминала:
curl '127.0.0.1:8000/?name=world'Hello, world!
Method: GETПроцесс между запросами никуда не девается: Rapira один раз форкает воркеров и держит внутри каждого поднятый интерпретатор PHP. Выбрасывается другое — состояние самого скрипта: переменные, автозагрузчик, всё, что успел построить фреймворк.
Режим воркера
Режим SAPI Worker оставляет скрипт живым. Он поднимается один раз, а дальше в цикле получает от Rapira очередной запрос; Rapira заново наполняет суперглобальные переменные и вызывает ваш обработчик. Код PHP выглядит привычно: вы всё так же читаете $_GET и отдаёте ответ через echo, но приложение поднимается один раз на процесс, а не на каждый запрос. Подробнее — в разделе Режимы выполнения.
Создайте worker.php в корне проекта:
<?php
use Rapira\Plugin\Http\HttpHandlerConfig;
use function Rapira\create_plugin_handler;
$http = create_plugin_handler(new HttpHandlerConfig());
// Outside the loop, so it survives every request this worker serves.
$handled = 0;
$handler = static function () use (&$handled): void {
$handled++;
header('Content-Type: text/plain');
echo "Hello, " . ($_GET['name'] ?? 'anonymous') . "!\n";
echo "worker " . getmypid() . " handled {$handled} request(s)\n";
};
while ($http->handleRequest($handler)) {
gc_collect_cycles();
}create_plugin_handler() возвращает обработчик, который занимается HTTP; какой именно, определяет переданный ему HttpHandlerConfig. Дальше handleRequest() блокируется до прихода запроса, выполняет для него ваш колбэк и возвращает true; когда сервер начинает останавливаться, он возвращает false — на этом цикл и заканчивается.
create_plugin_handler(), HttpHandlerConfig и классы обработчиков живут в PHP-модуле, который Rapira регистрирует при старте интерпретатора, поэтому скрипт выше работает без автозагрузчика. Приложение с зависимостями Composer подключает свой vendor/autoload.php до цикла.
Сначала остановите классический сервер: нажмите Ctrl-C в его терминале, ведь оба слушают один и тот же адрес 127.0.0.1:8000. Режим воркера включён по умолчанию, так что флаг в этот раз не нужен:
rapira serve worker.phpcurl '127.0.0.1:8000/?name=world'Повторите curl несколько раз: счётчик растёт, потому что запросы обслуживает один и тот же процесс. По умолчанию Rapira форкает по воркеру на каждое логическое ядро, поэтому запрос может попасть в любой из них — какой воркер его примет, решает операционная система. Счётчик у каждого воркера свой, а pid в ответе показывает, кто именно ответил. Если нужно, чтобы счётчик рос одной последовательностью, запустите rapira serve --processes 1 worker.php. О том, как супервизор присматривает за пулом, рассказывает модель процессов.
Всё, что вы построили до цикла while, остаётся в памяти на всё время жизни воркера: автозагрузчик Composer, DI-контейнер, соединения с базой данных и кешем, скомпилированные маршруты и шаблоны. Всё это строится один раз, при старте, а не на каждом запросе. Заново создаётся только то, что относится к конкретному запросу.
Состояние, которое остаётся между запросами, должен сбрасывать сам скрипт воркера. Статическое свойство, глобальная переменная, незакрытая транзакция — всё, что оставил после себя один запрос, достанется следующему. На что здесь смотреть и как держать воркер в чистоте, разбирает Режим воркера.
Внутри обработчика работают привычные функции: header(), http_response_code(), echo, а также rapira_finish_request() — она отдаёт ответ раньше времени и позволяет продолжить работу после этого. Подробнее — в разделе HTTP.
Файл конфигурации
Настройки можно держать в файле rapira.toml, а не передавать в командной строке. Для начала достаточно файла рядом с кодом:
[http]
listen = "127.0.0.1:8000"
[pool]
entrypoint = "worker.php"
processes = 4rapira serve --config rapira.tomlОтносительный pool.entrypoint считается от каталога самого файла конфигурации, поэтому один и тот же файл работает из любого текущего каталога. Флаги по-прежнему сильнее файла: rapira serve --config rapira.toml --processes 1 оставит остальные настройки как есть и поднимет всего один воркер.
Файл также принимает режимы масштабирования пула, пересоздание воркеров, таймауты запросов, логирование и pidfile супервизора. Незнакомые ключи не игнорируются, а отвергаются, поэтому опечатка прерывает запуск, а не остаётся без всякого эффекта. Полный справочник — в Конфигурации, а флаги — в разделе Командная строка.
Остановка сервера
Нажмите Ctrl-C, и Rapira уйдёт в мягкое завершение: перестанет брать новую работу, даст доработать уже начатым запросам, выключит расширения и выйдет. Второй Ctrl-C пропускает ожидание и завершает процесс принудительно, поэтому зависший запрос не удерживает сервер. SIGTERM ведёт себя точно так же, поэтому перезапуск из менеджера служб проходит аккуратно. Полная таблица сигналов, включая перезагрузку без разрыва соединений, есть в разделе Модель процессов.
Что дальше
- Режим воркера — подробно о резидентном цикле: состояние, утечки, пересоздание воркеров и то, как поднять настоящее приложение до входа в цикл.
- Конфигурация — все ключи, которые принимает
rapira.toml, вместе со значениями по умолчанию. - Фреймворки — руководства по интеграции для Symfony, Laravel и Yii3.