diff --git a/docs/cn/worker.md b/docs/cn/worker.md index cc0a7be1d..c4a8eb387 100644 --- a/docs/cn/worker.md +++ b/docs/cn/worker.md @@ -35,8 +35,13 @@ frankenphp php-server --worker /path/to/your/worker/script.php frankenphp php-server --worker /path/to/your/worker/script.php --watch="/path/to/your/app/**/*.php" ``` +此功能通常与[热重载](hot-reload.md)结合使用。 + ## Symfony Runtime +> [!TIP] +> 以下部分仅在 Symfony 7.4 之前是必需的,因为 Symfony 7.4 引入了对 FrankenPHP worker 模式的原生支持。 + FrankenPHP 的 worker 模式由 [Symfony Runtime Component](https://symfony.com/doc/current/components/runtime.html) 支持。 要在 worker 中启动任何 Symfony 应用程序,请安装 [PHP Runtime](https://github.com/php-runtime/runtime) 的 FrankenPHP 包: @@ -67,9 +72,6 @@ docker run \ boot(); // 在循环外的处理器以获得更好的性能(减少工作量) $handler = static function () use ($myApp) { - // 当收到请求时调用, - // 超全局变量、php://input 等都会被重置 - echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + try { + // 当收到请求时调用, + // 超全局变量、php://input 等都会被重置 + echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + } catch (\Throwable $exception) { + // `set_exception_handler` 仅在 worker 脚本结束时调用, + // 这可能不是您所期望的,因此在此处捕获并处理异常 + (new \MyCustomExceptionHandler)->handleException($exception); + } }; $maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0); @@ -144,7 +152,7 @@ curl -X POST http://localhost:2019/frankenphp/workers/restart 但是,如果 worker 脚本在短时间内继续以非零退出代码失败 (例如,脚本中有拼写错误),FrankenPHP 将崩溃并出现错误:`too many consecutive failures`。 -可以在你的 [Caddyfile](config.md#caddyfile-配置) 中使用 `max_consecutive_failures` 选项配置连续失败的次数: +可以在你的 [Caddyfile](config.md#caddyfile-config) 中使用 `max_consecutive_failures` 选项配置连续失败的次数: ```caddyfile frankenphp { @@ -157,7 +165,7 @@ frankenphp { ## 超全局变量行为 -[PHP 超全局变量](https://www.php.net/manual/zh/language.variables.superglobals.php)(`$_SERVER`、`$_ENV`、`$_GET`...) +[PHP 超全局变量](https://www.php.net/manual/en/language.variables.superglobals.php)(`$_SERVER`、`$_ENV`、`$_GET`...) 行为如下: - 在第一次调用 `frankenphp_handle_request()` 之前,超全局变量包含绑定到 worker 脚本本身的值 @@ -176,4 +184,3 @@ $handler = static function () use ($workerServer) { }; // ... -``` diff --git a/docs/fr/worker.md b/docs/fr/worker.md index 3aab2cec9..24f764b23 100644 --- a/docs/fr/worker.md +++ b/docs/fr/worker.md @@ -19,22 +19,24 @@ docker run \ ### Binaire autonome -Utilisez l'option --worker de la commande php-server pour servir le contenu du répertoire courant en utilisant un worker : +Utilisez l'option `--worker` de la commande `php-server` pour servir le contenu du répertoire courant en utilisant un worker : ```console frankenphp php-server --worker /path/to/your/worker/script.php ``` -Si votre application PHP est [intégrée dans le binaire](embed.md), vous pouvez également ajouter un `Caddyfile` personnalisé dans le répertoire racine de l'application. +Si votre application PHP est [intégrée dans le binaire](embed.md), vous pouvez ajouter un `Caddyfile` personnalisé dans le répertoire racine de l'application. Il sera utilisé automatiquement. -Il est également possible de [redémarrer le worker en cas de changement de fichier](config.md#surveillance-des-modifications-de-fichier) avec l'option `--watch`. +Il est également possible de [redémarrer le worker en cas de changement de fichier](config.md#watching-for-file-changes) avec l'option `--watch`. La commande suivante déclenchera un redémarrage si un fichier se terminant par `.php` dans le répertoire `/path/to/your/app/` ou ses sous-répertoires est modifié : ```console frankenphp php-server --worker /path/to/your/worker/script.php --watch="/path/to/your/app/**/*.php" ``` +Cette fonctionnalité est souvent utilisée en combinaison avec le [rechargement à chaud](hot-reload.md). + ## Runtime Symfony > [!TIP] @@ -70,20 +72,23 @@ L'exemple suivant montre comment créer votre propre script worker sans dépendr boot(); -// En dehors de la boucle pour de meilleures performances (moins de travail effectué) +// Gestionnaire en dehors de la boucle pour de meilleures performances (moins de travail effectué) $handler = static function () use ($myApp) { - // Appelé lorsqu'une requête est reçue, - // les superglobales, php://input, etc., sont réinitialisés - echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + try { + // Appelé lorsqu'une requête est reçue, + // les superglobales, php://input, etc., sont réinitialisés + echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + } catch (\Throwable $exception) { + // `set_exception_handler` est appelé uniquement lorsque le script worker se termine, + // ce qui peut ne pas être ce que vous attendez, alors interceptez et gérez les exceptions ici + (new \MyCustomExceptionHandler)->handleException($exception); + } }; $maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0); @@ -133,27 +138,23 @@ Le code du worker précédent permet de configurer un nombre maximal de requête ### Redémarrer les workers manuellement -Bien qu'il soit possible de redémarrer les workers [en cas de changement de fichier](config.md#surveillance-des-modifications-de-fichier), +Bien qu'il soit possible de redémarrer les workers [en cas de changement de fichier](config.md#watching-for-file-changes), il est également possible de redémarrer tous les workers de manière élégante via l'[API Admin de Caddy](https://caddyserver.com/docs/api). -Si l'administration est activée dans votre [Caddyfile](config.md#configuration-du-caddyfile), vous pouvez envoyer un ping +Si l'administration est activée dans votre [Caddyfile](config.md#caddyfile-config), vous pouvez envoyer un ping à l'endpoint de redémarrage avec une simple requête POST comme celle-ci : ```console curl -X POST http://localhost:2019/frankenphp/workers/restart ``` -> [!NOTE] -> -> C'est une fonctionnalité expérimentale et peut être modifiée ou supprimée dans le futur. - -### Worker Failures +### Échecs des workers Si un script de worker se plante avec un code de sortie non nul, FrankenPHP le redémarre avec une stratégie de backoff exponentielle. Si le script worker reste en place plus longtemps que le dernier backoff \* 2, FrankenPHP ne pénalisera pas le script et le redémarrera à nouveau. Toutefois, si le script de worker continue d'échouer avec un code de sortie non nul dans un court laps de temps (par exemple, une faute de frappe dans un script), FrankenPHP plantera avec l'erreur : `too many consecutive failures` (trop d'échecs consécutifs). -Le nombre d'échecs consécutifs peut être configuré dans votre [Caddyfile](config.md#configuration-du-caddyfile) avec l'option `max_consecutive_failures` : +Le nombre d'échecs consécutifs peut être configuré dans votre [Caddyfile](config.md#caddyfile-config) avec l'option `max_consecutive_failures` : ```caddyfile frankenphp { @@ -185,4 +186,3 @@ $handler = static function () use ($workerServer) { }; // ... -``` diff --git a/docs/ja/worker.md b/docs/ja/worker.md index 3440d0c38..aa71b6d3b 100644 --- a/docs/ja/worker.md +++ b/docs/ja/worker.md @@ -35,8 +35,13 @@ PHPアプリが[バイナリに埋め込まれている](embed.md)場合は、 frankenphp php-server --worker /path/to/your/worker/script.php --watch="/path/to/your/app/**/*.php" ``` +この機能は、[ホットリロード](hot-reload.md)と組み合わせてよく使用されます。 + ## Symfonyランタイム +> [!TIP] +> 以下のセクションは、FrankenPHPワーカーモードのネイティブサポートが導入されたSymfony 7.4より前のバージョンでのみ必要です。 + FrankenPHPのワーカーモードは[Symfony Runtime Component](https://symfony.com/doc/current/components/runtime.html)によってサポートされています。 ワーカーでSymfonyアプリケーションを開始するには、FrankenPHP用の[PHP Runtime](https://github.com/php-runtime/runtime)パッケージをインストールします: @@ -67,30 +72,33 @@ docker run \ boot(); -// ループの外側にハンドラーを配置してパフォーマンスを向上(処理量を減らす) +// パフォーマンス向上のため、ループの外側にハンドラーを配置(処理を減らす) $handler = static function () use ($myApp) { - // リクエストを受信した際に呼び出され、 - // スーパーグローバルや php://input などがリセットされます。 - echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + try { + // リクエストを受信すると呼び出され、 + // スーパーグローバル、php://inputなどがリセットされます。 + echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + } catch (\Throwable $exception) { + // `set_exception_handler`はワーカースクリプトが終了するときにのみ呼び出されるため、 + // 予期しない動作になる可能性があります。そのため、ここで例外をキャッチして処理します。 + (new \MyCustomExceptionHandler)->handleException($exception); + } }; $maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0); for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests) { $keepRunning = \frankenphp_handle_request($handler); - // HTTPレスポンスの送信後に何か処理を行います + // HTTPレスポンス送信後に何らかの処理を実行 $myApp->terminate(); - // ページ生成の途中でガベージコレクタが起動する可能性を減らすために、ここでガベージコレクタを明示的に呼び出す。 + // ページ生成中にガベージコレクタが起動する可能性を減らすため、ここでガベージコレクタを明示的に呼び出す gc_collect_cycles(); if (!$keepRunning) break; @@ -178,4 +186,3 @@ $handler = static function () use ($workerServer) { }; // ... -``` diff --git a/docs/pt-br/worker.md b/docs/pt-br/worker.md index a835be5f7..64c442264 100644 --- a/docs/pt-br/worker.md +++ b/docs/pt-br/worker.md @@ -1,18 +1,17 @@ -# Usando workers do FrankenPHP +# Usando Workers do FrankenPHP Inicialize sua aplicação uma vez e mantenha-a na memória. O FrankenPHP processará as requisições recebidas em poucos milissegundos. -## Iniciando worker scripts +## Iniciando Worker Scripts ### Docker -Defina o valor da variável de ambiente `FRANKENPHP_CONFIG` como -`worker /caminho/para/seu/worker/script.php`: +Defina o valor da variável de ambiente `FRANKENPHP_CONFIG` como `worker /path/to/your/worker/script.php`: ```console docker run \ - -e FRANKENPHP_CONFIG="worker /app/caminho/para/seu/worker/script.php" \ + -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 @@ -20,41 +19,37 @@ docker run \ ### Binário independente -Use a opção `--worker` do comando `php-server` para servir o conteúdo do -diretório atual usando um worker: +Use a opção `--worker` do comando `php-server` para servir o conteúdo do diretório atual usando um worker: ```console -frankenphp php-server --worker /caminho/para/seu/worker/script.php +frankenphp php-server --worker /path/to/your/worker/script.php ``` -Se a sua aplicação PHP estiver [embutida no binário](embed.md), você pode -adicionar um `Caddyfile` personalizado no diretório raiz da aplicação. +Se a sua aplicação PHP estiver [embutida no binário](embed.md), você pode adicionar um `Caddyfile` personalizado no diretório raiz da aplicação. Ele será usado automaticamente. -Também é possível -[reiniciar o worker em caso de alterações em arquivos](config.md#monitorando-alteracoes-em-arquivos) -com a opção `--watch`. -O comando a seguir acionará uma reinicialização se qualquer arquivo terminado em -`.php` no diretório `/caminho/para/sua/aplicacao/` ou subdiretórios for -modificado: +Também é possível [reiniciar o worker em caso de alterações em arquivos](config.md#watching-for-file-changes) com a opção `--watch`. +O comando a seguir acionará uma reinicialização se qualquer arquivo terminado em `.php` no diretório `/path/to/your/app/` ou subdiretórios for modificado: ```console -frankenphp php-server --worker /caminho/para/seu/worker/script.php --watch="/caminho/para/sua/aplicacao/**/*.php" +frankenphp php-server --worker /path/to/your/worker/script.php --watch="/path/to/your/app/**/*.php" ``` +Este recurso é frequentemente usado em combinação com [hot reloading](hot-reload.md). + ## Symfony Runtime -O modo worker do FrankenPHP é suportado pelo -[Componente Symfony Runtime](https://symfony.com/doc/current/components/runtime.html). -Para iniciar qualquer aplicação Symfony em um worker, instale o pacote -FrankenPHP do [PHP Runtime](https://github.com/php-runtime/runtime): +> [!TIP] +> A seção a seguir é necessária apenas antes do Symfony 7.4, onde o suporte nativo para o modo worker do FrankenPHP foi introduzido. + +O modo worker do FrankenPHP é suportado pelo [Componente Symfony Runtime](https://symfony.com/doc/current/components/runtime.html). +Para iniciar qualquer aplicação Symfony em um worker, instale o pacote FrankenPHP do [PHP Runtime](https://github.com/php-runtime/runtime): ```console composer require runtime/frankenphp-symfony ``` -Inicie seu servidor de aplicações definindo a variável de ambiente `APP_RUNTIME` -para usar o Symfony Runtime do FrankenPHP: +Inicie seu servidor de aplicações definindo a variável de ambiente `APP_RUNTIME` para usar o Symfony Runtime do FrankenPHP: ```console docker run \ @@ -71,17 +66,12 @@ Consulte [a documentação dedicada](laravel.md#laravel-octane). ## Aplicações personalizadas -O exemplo a seguir mostra como criar seu próprio worker script sem depender de -uma biblioteca de terceiros: +O exemplo a seguir mostra como criar seu próprio worker script sem depender de uma biblioteca de terceiros: ```php boot(); // Manipulador fora do loop para melhor desempenho (fazendo menos trabalho) $handler = static function () use ($myApp) { - // Chamado quando uma requisição é recebida, - // superglobals, php://input e similares são redefinidos - echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + try { + // Chamado quando uma requisição é recebida, + // superglobais, php://input e similares são redefinidos + echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + } catch (\Throwable $exception) { + // `set_exception_handler` é chamado apenas quando o worker script termina, + // o que pode não ser o que você espera, então capture e trate exceções aqui + (new \MyCustomExceptionHandler)->handleException($exception); + } }; $maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0); @@ -102,8 +98,7 @@ for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests // Faz algo depois de enviar a resposta HTTP $myApp->terminate(); - // Chama o coletor de lixo para reduzir as chances de ele ser acionado no - // meio da geração de uma página + // Chama o coletor de lixo para reduzir as chances de ele ser acionado no meio da geração de uma página gc_collect_cycles(); if (!$keepRunning) break; @@ -113,8 +108,7 @@ for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests $myApp->shutdown(); ``` -Em seguida, inicie sua aplicação e use a variável de ambiente -`FRANKENPHP_CONFIG` para configurar seu worker: +Em seguida, inicie sua aplicação e use a variável de ambiente `FRANKENPHP_CONFIG` para configurar seu worker: ```console docker run \ @@ -135,44 +129,28 @@ docker run \ dunglas/frankenphp ``` -### Reiniciar o worker após um certo número de requisições +### Reiniciar o Worker Após um Certo Número de Requisições -Como o PHP não foi originalmente projetado para processos de longa duração, -ainda existem muitas bibliotecas e códigos legados que vazam memória. -Uma solução alternativa para usar esse tipo de código no modo worker é reiniciar -o worker script após processar um certo número de requisições: +Como o PHP não foi originalmente projetado para processos de longa duração, ainda existem muitas bibliotecas e códigos legados que vazam memória. +Uma solução alternativa para usar esse tipo de código no modo worker é reiniciar o worker script após processar um certo número de requisições: -O trecho de código de worker anterior permite configurar um número máximo de -requisições a serem processadas, definindo uma variável de ambiente chamada -`MAX_REQUESTS`. +O trecho de código de worker anterior permite configurar um número máximo de requisições a serem processadas, definindo uma variável de ambiente chamada `MAX_REQUESTS`. -### Reiniciar os workers manualmente +### Reiniciar os Workers Manualmente -Embora seja possível reiniciar os workers -[em alterações de arquivo](config.md#monitorando-alteracoes-em-arquivos), também -é possível reiniciar todos os workers graciosamente por meio da -[API de administração do Caddy](https://caddyserver.com/docs/api). -Se o administrador estiver habilitado no seu -[Caddyfile](config.md#configuracao-do-caddyfile), você pode executar ping no -endpoint de reinicialização com uma simples requisição POST como esta: +Embora seja possível reiniciar os workers [em alterações de arquivo](config.md#watching-for-file-changes), também é possível reiniciar todos os workers graciosamente por meio da [API de administração do Caddy](https://caddyserver.com/docs/api). Se o administrador estiver habilitado no seu [Caddyfile](config.md#caddyfile-config), você pode acionar o endpoint de reinicialização com uma simples requisição POST como esta: ```console curl -X POST http://localhost:2019/frankenphp/workers/restart ``` -### Falhas de worker +### Falhas de Worker -Se um worker script travar com um código de saída diferente de zero, o -FrankenPHP o reiniciará com uma estratégia de backoff exponencial. -Se o worker script permanecer ativo por mais tempo do que o último backoff \* 2, -ele não irá penalizar o worker script e reiniciá-lo novamente. -No entanto, se o worker script continuar a falhar com um código de saída -diferente de zero em um curto período de tempo (por exemplo, com um erro de -digitação em um script), o FrankenPHP travará com o erro: -`too many consecutive failures` (muitas falhas consecutivas). +Se um worker script travar com um código de saída diferente de zero, o FrankenPHP o reiniciará com uma estratégia de backoff exponencial. +Se o worker script permanecer ativo por mais tempo do que o último backoff \* 2, ele não irá penalizar o worker script e reiniciá-lo novamente. +No entanto, se o worker script continuar a falhar com um código de saída diferente de zero em um curto período de tempo (por exemplo, com um erro de digitação em um script), o FrankenPHP travará com o erro: `too many consecutive failures`. -O número de falhas consecutivas pode ser configurado no seu -[Caddyfile](config.md#caddyfile-config) com a opção `max_consecutive_failures`: +O número de falhas consecutivas pode ser configurado no seu [Caddyfile](config.md#caddyfile-config) com a opção `max_consecutive_failures`: ```caddyfile frankenphp { @@ -183,21 +161,14 @@ frankenphp { } ``` -## Comportamento das superglobais +## Comportamento das Superglobais -As -[superglobais do PHP](https://www.php.net/manual/pt_BR/language.variables.superglobals.php) -(`$_SERVER`, `$_ENV`, `$_GET`...) se comportam da seguinte maneira: +As [superglobais do PHP](https://www.php.net/manual/pt_BR/language.variables.superglobals.php) (`$_SERVER`, `$_ENV`, `$_GET`...) se comportam da seguinte maneira: -- antes da primeira chamada para `frankenphp_handle_request()`, as superglobais - contêm valores vinculados ao próprio worker script. -- durante e após a chamada para `frankenphp_handle_request()`, as superglobais - contêm valores gerados a partir da requisição HTTP processada. - Cada chamada para `frankenphp_handle_request()` altera os valores das - superglobais. +- antes da primeira chamada para `frankenphp_handle_request()`, as superglobais contêm valores vinculados ao próprio worker script. +- durante e após a chamada para `frankenphp_handle_request()`, as superglobais contêm valores gerados a partir da requisição HTTP processada. Cada chamada para `frankenphp_handle_request()` altera os valores das superglobais. -Para acessar as superglobais do worker script dentro do retorno de chamada, você -deve copiá-las e importar a cópia para o escopo do retorno de chamada: +Para acessar as superglobais do worker script dentro do retorno de chamada, você deve copiá-las e importar a cópia para o escopo do retorno de chamada: ```php [!СОВЕТ] +> Следующий раздел актуален только для версий Symfony до 7.4, где была введена нативная поддержка режима воркеров FrankenPHP. + +Worker режим FrankenPHP поддерживается компонентом [Symfony Runtime](https://symfony.com/doc/current/components/runtime.html). Чтобы запустить любое Symfony-приложение в worker режиме, установите пакет FrankenPHP для [PHP Runtime](https://github.com/php-runtime/runtime): ```console @@ -57,7 +62,7 @@ docker run \ ## Laravel Octane -Подробнее см. в [документации](laravel.md#laravel-octane). +Подробнее см. в [отдельной документации](laravel.md#laravel-octane). ## Пользовательские приложения @@ -67,20 +72,23 @@ docker run \ boot(); -// Обработчик запросов за пределами цикла для повышения производительности +// Обработчик запросов за пределами цикла для повышения производительности (выполняет меньше работы) $handler = static function () use ($myApp) { - // Выполняется при обработке запроса. - // Суперглобальные переменные, php://input и другие данные обновляются для каждого запроса. - echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + try { + // Выполняется при получении запроса, + // суперглобальные переменные, php://input и прочие сбрасываются + echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + } catch (\Throwable $exception) { + // `set_exception_handler` вызывается только когда worker-скрипт завершается, + // что может быть не тем, что вы ожидаете, поэтому перехватывайте и обрабатывайте исключения здесь + (new \MyCustomExceptionHandler)->handleException($exception); + } }; $maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0); @@ -96,11 +104,11 @@ for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests if (!$keepRunning) break; } -// Завершение +// Очистка $myApp->shutdown(); ``` -Запустите приложение, настроив worker-скрипт с помощью переменной окружения `FRANKENPHP_CONFIG`: +Запустите ваше приложение и используйте переменную окружения `FRANKENPHP_CONFIG` для настройки вашего воркера: ```console docker run \ @@ -110,10 +118,7 @@ docker run \ dunglas/frankenphp ``` -## Настройка количества worker-скриптов - -По умолчанию запускается по 2 worker-скрипта на каждый CPU. -Вы можете задать своё значение: +По умолчанию запускается 2 воркера на каждый CPU. Вы также можете настроить количество запускаемых воркеров: ```console docker run \ @@ -125,35 +130,54 @@ docker run \ ### Перезапуск worker-скрипта после определённого количества запросов -PHP изначально не предназначался для долгоживущих процессов, поэтому некоторые библиотеки и устаревший код могут приводить к утечкам памяти. -Для этого можно настроить автоматический перезапуск worker-скрипта после обработки определённого количества запросов. +PHP изначально не предназначался для долгоживущих процессов, поэтому есть ещё много библиотек и устаревшего кода, которые вызывают утечки памяти. +Обходной путь для использования такого кода в режиме воркера состоит в перезапуске скрипта воркера после обработки определённого количества запросов: + +Предыдущий сниппет воркера позволяет настроить максимальное количество запросов для обработки, установив переменную окружения с именем `MAX_REQUESTS`. + +### Перезапуск воркеров вручную + +Хотя можно перезапускать воркеры [при изменении файлов](config.md#watching-for-file-changes), также можно корректно перезапустить все воркеры через [API администрирования Caddy](https://caddyserver.com/docs/api). Если администрирование включено в вашем [Caddyfile](config.md#caddyfile-config), вы можете отправить запрос POST на конечную точку перезапуска следующим образом: -В предыдущем примере максимальное количество запросов задаётся с помощью переменной окружения `MAX_REQUESTS`. +```console +curl -X POST http://localhost:2019/frankenphp/workers/restart +``` ### Сбои worker-скрипта -Если worker-скрипт завершится с ненулевым кодом выхода, FrankenPHP перезапустит его с использованием экспоненциальной задержки. -Если worker-скрипт проработает дольше, чем время последней задержки \* 2, он будет считаться стабильным, и задержка сбросится. -Однако, если worker-скрипт продолжает завершаться с ненулевым кодом выхода в течение короткого промежутка времени (например, из-за опечатки в коде), FrankenPHP завершит работу с ошибкой: `too many consecutive failures`. +Если worker-скрипт завершится с ненулевым кодом выхода, FrankenPHP перезапустит его со стратегией экспоненциальной задержки. +Если скрипт воркера остается активным дольше, чем время последней задержки \* 2, FrankenPHP не будет применять штраф к worker-скрипту и перезапустит его снова. +Однако, если worker-скрипт продолжает завершаться с ненулевым кодом выхода в течение короткого промежутка времени +(например, из-за опечатки в скрипте), FrankenPHP завершит работу с ошибкой: `too many consecutive failures`. + +Количество последовательных сбоев можно настроить в вашем [Caddyfile](config.md#caddyfile-config) с помощью опции `max_consecutive_failures`: + +```caddyfile +frankenphp { + worker { + # ... + max_consecutive_failures 10 + } +} +``` ## Поведение суперглобальных переменных -[PHP суперглобальные переменные](https://www.php.net/manual/en/language.variables.superglobals.php) (`$_SERVER`, `$_ENV`, `$_GET` и т.д.) ведут себя следующим образом: +[PHP суперглобальные переменные](https://www.php.net/manual/en/language.variables.superglobals.php) (`$_SERVER`, `$_ENV`, `$_GET`...) ведут себя следующим образом: -- до первого вызова `frankenphp_handle_request()` суперглобальные переменные содержат значения, связанные с самим worker-скриптом -- во время и после вызова `frankenphp_handle_request()` суперглобальные переменные содержат значения, сгенерированные на основе обработанного HTTP-запроса, каждый вызов изменяет значения суперглобальных переменных +- до первого вызова `frankenphp_handle_request()`, суперглобальные переменные содержат значения, связанные с самим worker-скриптом +- во время и после вызова `frankenphp_handle_request()`, суперглобальные переменные содержат значения, сгенерированные на основе обработанного HTTP-запроса, каждый вызов `frankenphp_handle_request()` изменяет значения суперглобальных переменных Чтобы получить доступ к суперглобальным переменным worker-скрипта внутри колбэка, необходимо скопировать их и импортировать копию в область видимости колбэка: ```php [!TIP] +> Bu bölüm, FrankenPHP worker moduna yerel desteğin sunulduğu Symfony 7.4 öncesi için gereklidir. + FrankenPHP'nin worker modu [Symfony Runtime Component](https://symfony.com/doc/current/components/runtime.html) tarafından desteklenmektedir. Herhangi bir Symfony uygulamasını bir worker'da başlatmak için [PHP Runtime](https://github.com/php-runtime/runtime)'ın FrankenPHP paketini yükleyin: @@ -50,19 +62,16 @@ docker run \ ## Laravel Octane -Bkz. [ilgili doküman](laravel.md#laravel-octane). +Bkz. [özel dokümantasyon](laravel.md#laravel-octane). ## Özel Uygulamalar -Aşağıdaki örnek, üçüncü taraf bir kütüphaneye güvenmeden kendi çalışan kodunuzu nasıl oluşturacağınızı göstermektedir: +Aşağıdaki örnek, üçüncü taraf bir kütüphaneye güvenmeden kendi worker betiğinizi nasıl oluşturacağınızı göstermektedir: ```php boot(); // Daha iyi performans için döngü dışında işleyici (daha az iş yapıyor) $handler = static function () use ($myApp) { - // Bir istek alındığında çağrılır, - // superglobals, php://input ve benzerleri sıfırlanır - echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + try { + // Bir istek alındığında çağrılır, + // süper küresel değişkenler, php://input ve benzerleri sıfırlanır + echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER); + } catch (\Throwable $exception) { + // `set_exception_handler` yalnızca worker betiği sona erdiğinde çağrılır, + // bu beklediğiniz gibi olmayabilir, bu yüzden istisnaları burada yakalayın ve ele alın + (new \MyCustomExceptionHandler)->handleException($exception); + } }; -for ($nbRequests = 0, $running = true; isset($_SERVER['MAX_REQUESTS']) && ($nbRequests < ((int)$_SERVER['MAX_REQUESTS'])) && $running; ++$nbRequests) { - $running = \frankenphp_handle_request($handler); +$maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0); +for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests) { + $keepRunning = \frankenphp_handle_request($handler); // HTTP yanıtını gönderdikten sonra bir şey yapın $myApp->terminate(); // Bir sayfa oluşturmanın ortasında tetiklenme olasılığını azaltmak için çöp toplayıcıyı çağırın gc_collect_cycles(); + + if (!$keepRunning) break; } // Temizleme $myApp->shutdown(); ``` -Ardından, uygulamanızı başlatın ve çalışanınızı yapılandırmak için `FRANKENPHP_CONFIG` ortam değişkenini kullanın: +Ardından, uygulamanızı başlatın ve worker'ınızı yapılandırmak için `FRANKENPHP_CONFIG` ortam değişkenini kullanın: ```console docker run \ @@ -113,12 +131,51 @@ docker run \ ### Belirli Sayıda İstekten Sonra Worker'ı Yeniden Başlatın - +PHP başlangıçta uzun süreli işlemler için tasarlanmadığından, hala bellek sızdıran birçOK kütüphane ve eski kod vardır. +Bu tür kodları worker modunda kullanmak için geçici bir çözüm, belirli sayıda isteği işledikten sonra worker betiğini yeniden başlatmaktır: -PHP başlangıçta uzun süreli işlemler için tasarlanmadığından, hala bellek sızdıran birçok kütüphane ve eski kod vardır. +Önceki worker kod parçacığı, `MAX_REQUESTS` adlı bir ortam değişkeni ayarlayarak işlenecek maksimum istek sayısını yapılandırmaya izin verir. - +### Worker'ları Manuel Olarak Yeniden Başlatma -Bu tür kodları worker modunda kullanmak için geçici bir çözüm, belirli sayıda isteği işledikten sonra worker betiğini yeniden başlatmaktır: +Worker'ları [dosya değişikliklerinde](config.md#watching-for-file-changes) yeniden başlatmak mümkünken, tüm worker'ları [Caddy admin API](https://caddyserver.com/docs/api) aracılığıyla sorunsuz bir şekilde yeniden başlatmak da mümkündür. Yönetici [Caddyfile](config.md#caddyfile-config)'ınızda etkinleştirilmişse, yeniden başlatma uç noktasına aşağıdaki gibi basit bir POST isteği gönderebilirsiniz: -Önceki worker kod parçacığı, `MAX_REQUESTS` adlı bir ortam değişkeni ayarlayarak işlenecek maksimum istek sayısını yapılandırmaya izin verir. +```console +curl -X POST http://localhost:2019/frankenphp/workers/restart +``` + +### Worker Hataları + +Bir worker betiği sıfır olmayan bir çıkış koduyla çökerse, FrankenPHP onu üstel bir geri çekilme (exponential backoff) stratejisiyle yeniden başlatacaktır. Worker betiği, son geri çekilme süresinin 2 katından daha uzun süre çalışır durumda kalırsa, worker betiğini cezalandırmayacak ve tekrar yeniden başlatacaktır. Ancak, worker betiği kısa bir süre içinde sıfır olmayan bir çıkış koduyla başarısız olmaya devam ederse (örneğin, bir betikte yazım hatası olması durumunda), FrankenPHP `too many consecutive failures` hatasıyla çökecektir. + +Ardışık hata sayısı, [Caddyfile](config.md#caddyfile-config)'ınızda `max_consecutive_failures` seçeneği ile yapılandırılabilir: + +```caddyfile +frankenphp { + worker { + # ... + max_consecutive_failures 10 + } +} +``` + +## Süper Küresel Değişkenlerin Davranışı + +[PHP süper küresel değişkenleri](https://www.php.net/manual/en/language.variables.superglobals.php) (`$_SERVER`, `$_ENV`, `$_GET`...) aşağıdaki gibi davranır: + +- `frankenphp_handle_request()`'e ilk çağrıdan önce, süper küresel değişkenler worker betiğinin kendisine bağlı değerleri içerir +- `frankenphp_handle_request()` çağrısı sırasında ve sonrasında, süper küresel değişkenler işlenen HTTP isteğinden üretilen değerleri içerir, `frankenphp_handle_request()`'e yapılan her çağrı süper küresel değişken değerlerini değiştirir + +Geri çağırım içinde worker betiğinin süper küresel değişkenlerine erişmek için, bunları kopyalamalı ve kopyayı geri çağırımın kapsamına aktarmalısınız: + +```php +