Эта страница была переведена сообществом и не обязательно является актуальной. Обратитесь к справочной версии.

Эта страница была переведена сообществом и не обязательно является актуальной. Обратитесь к справочной версии.

Эта страница была переведена сообществом и не обязательно является актуальной. Обратитесь к справочной версии.

Спонсор
Worker режим в FrankenPHP

Worker режим в FrankenPHP

Загрузите приложение один раз и держите его в памяти.
FrankenPHP обрабатывает входящие запросы за несколько миллисекунд.

# Запуск worker-скриптов

# Docker

Установите значение переменной окружения FRANKENPHP_CONFIG на worker /path/to/your/worker/script.php:

docker run \
    -e FRANKENPHP_CONFIG="worker /app/path/to/your/worker/script.php" \
    -v $PWD:/app \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp

# Автономный бинарный файл

Используйте опцию --worker команды php-server, чтобы обслуживать содержимое текущей директории через worker-скрипт:

frankenphp php-server --worker /path/to/your/worker/script.php

Если ваше PHP-приложение встроено в бинарник, вы можете добавить пользовательский Caddyfile в корневую директорию приложения.
Он будет использоваться автоматически.

Также можно настроить автоматический перезапуск worker-скрипта при изменении файлов с помощью опции --watch.
Следующая команда выполнит перезапуск, если будет изменён любой файл с расширением .php в директории /path/to/your/app/ или её поддиректориях:

frankenphp php-server --worker /path/to/your/worker/script.php --watch "/path/to/your/app/**/*.php"

# Symfony Runtime

Worker режим FrankenPHP поддерживается компонентом Symfony Runtime.
Чтобы запустить любое Symfony-приложение в worker режиме, установите пакет FrankenPHP для PHP Runtime:

composer require runtime/frankenphp-symfony

Запустите сервер приложения, задав переменную окружения APP_RUNTIME для использования FrankenPHP Symfony Runtime:

docker run \
    -e FRANKENPHP_CONFIG="worker ./public/index.php" \
    -e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
    -v $PWD:/app \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp

# Laravel Octane

Подробнее см. в документации.

# Пользовательские приложения

Следующий пример показывает, как создать собственный worker-скрипт без использования сторонних библиотек:

<?php
// public/index.php

// Предотвращает завершение worker-скрипта при разрыве соединения клиента
ignore_user_abort(true);

// Инициализация приложения
require __DIR__.'/vendor/autoload.php';

$myApp = new \App\Kernel();
$myApp->boot();

// Обработчик запросов за пределами цикла для повышения производительности
$handler = static function () use ($myApp) {
    // Выполняется при обработке запроса.
    // Суперглобальные переменные, php://input и другие данные обновляются для каждого запроса.
    echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
};

$maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0);
for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests) {
    $keepRunning = \frankenphp_handle_request($handler);

    // Действия после отправки HTTP-ответа
    $myApp->terminate();

    // Вызов сборщика мусора, чтобы снизить вероятность его запуска в процессе генерации страницы
    gc_collect_cycles();

    if (!$keepRunning) break;
}

// Завершение
$myApp->shutdown();

Запустите приложение, настроив worker-скрипт с помощью переменной окружения FRANKENPHP_CONFIG:

docker run \
    -e FRANKENPHP_CONFIG="worker ./public/index.php" \
    -v $PWD:/app \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp

# Настройка количества worker-скриптов

По умолчанию запускается по 2 worker-скрипта на каждый CPU.
Вы можете задать своё значение:

docker run \
    -e FRANKENPHP_CONFIG="worker ./public/index.php 42" \
    -v $PWD:/app \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp

# Перезапуск worker-скрипта после определённого количества запросов

PHP изначально не предназначался для долгоживущих процессов, поэтому некоторые библиотеки и устаревший код могут приводить к утечкам памяти.
Для этого можно настроить автоматический перезапуск worker-скрипта после обработки определённого количества запросов.

В предыдущем примере максимальное количество запросов задаётся с помощью переменной окружения MAX_REQUESTS.

# Сбои worker-скрипта

Если worker-скрипт завершится с ненулевым кодом выхода, FrankenPHP перезапустит его с использованием экспоненциальной задержки.
Если worker-скрипт проработает дольше, чем время последней задержки * 2, он будет считаться стабильным, и задержка сбросится.
Однако, если worker-скрипт продолжает завершаться с ненулевым кодом выхода в течение короткого промежутка времени (например, из-за опечатки в коде), FrankenPHP завершит работу с ошибкой: too many consecutive failures.

# Поведение суперглобальных переменных

PHP суперглобальные переменные ($_SERVER, $_ENV, $_GET и т.д.) ведут себя следующим образом:

  • до первого вызова frankenphp_handle_request() суперглобальные переменные содержат значения, связанные с самим worker-скриптом
  • во время и после вызова frankenphp_handle_request() суперглобальные переменные содержат значения, сгенерированные на основе обработанного HTTP-запроса, каждый вызов изменяет значения суперглобальных переменных

Чтобы получить доступ к суперглобальным переменным worker-скрипта внутри колбэка, необходимо скопировать их и импортировать копию в область видимости колбэка:

<?php
// Копирование $_SERVER worker-скрипта перед первым вызовом frankenphp_handle_request()
$workerServer = $_SERVER;

$handler = static function () use ($workerServer) {
    var_dump($_SERVER); // $_SERVER для запроса
    var_dump($workerServer); // $_SERVER worker-скрипта
};

// ...
Редактировать эту страницу