---
title: "Usando workers do FrankenPHP"
description: "Inicialize sua aplicação uma vez e mantenha-a na memória. O FrankenPHP processará as requisições recebidas em poucos milissegundos."
sidebar:
  label: "Modo worker"
  order: 1
---
## Iniciando worker scripts

### Docker

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/path/to/your/worker/script.php" \
    -v $PWD:/app \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp
```

### Binário independente

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 /path/to/your/worker/script.php
```

Se a sua aplicação PHP estiver [embutida no binário](/pt-br/docs/embed), 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](/pt-br/docs/config#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 /path/to/your/worker/script.php --watch="/path/to/your/app/**/*.php"
```

Este recurso é frequentemente usado em combinação com [hot reloading](/pt-br/docs/hot-reload).

## Symfony Runtime

<div class="fp-callout" data-callout="tip">
<p class="fp-callout-title">Dica</p>

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.

</div>

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:

```console
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

Consulte [a documentação dedicada](/pt-br/docs/laravel#laravel-octane).

## Aplicações personalizadas

O exemplo a seguir mostra como criar seu próprio worker script sem depender de uma biblioteca de terceiros:

```php
<?php
// public/index.php

// Inicializa a aplicação
require __DIR__.'/vendor/autoload.php';

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

// Manipulador fora do loop para melhor desempenho (fazendo menos trabalho)
$handler = static function () use ($myApp) {
    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);
for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests) {
    $keepRunning = \frankenphp_handle_request($handler);

    // 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
    gc_collect_cycles();

    if (!$keepRunning) break;
}

// Limpeza
$myApp->shutdown();
```

Em seguida, inicie sua aplicação e use a variável de ambiente `FRANKENPHP_CONFIG` para configurar seu worker:

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

Por padrão, são iniciados 2 workers por CPU.
Você também pode configurar o número de workers a serem iniciados:

```console
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
```

### 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:

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

Embora seja possível reiniciar os workers [em alterações de arquivo](/pt-br/docs/config#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](/pt-br/docs/config#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

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](/pt-br/docs/config#caddyfile-config) com a opção `max_consecutive_failures`:

```caddyfile
frankenphp {
    worker {
        # ...
        max_consecutive_failures 10
    }
}
```

## Comportamento das superglobais

As [superglobais do PHP](https://www.php.net/manual/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.

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
<?php
// Copia a superglobal $_SERVER do worker antes da primeira chamada para
// frankenphp_handle_request()
$workerServer = $_SERVER;

$handler = static function () use ($workerServer) {
    var_dump($_SERVER); // $_SERVER vinculada à requisição
    var_dump($workerServer); // $_SERVER do worker script
};

// ...
```
