Esta página ha sido traducida por la comunidad y puede no estar actualizada. Consulta la versión de referencia.
Esta página ha sido traducida por la comunidad y puede no estar actualizada. Consulta la versión de referencia.
Esta página ha sido traducida por la comunidad y puede no estar actualizada. Consulta la versión de referencia.
Inicia tu aplicación una vez y manténla en memoria. FrankenPHP gestionará las peticiones entrantes en unos pocos milisegundos.
Establece el valor de la variable de entorno FRANKENPHP_CONFIG a worker /ruta/a/tu/script/worker.php:
docker run \
-e FRANKENPHP_CONFIG="worker /app/ruta/a/tu/script/worker.php" \
-v $PWD:/app \
-p 80:80 -p 443:443 -p 443:443/udp \
dunglas/frankenphp
Usa la opción --worker del comando php-server para servir el contenido del directorio actual usando un worker:
frankenphp php-server --worker /ruta/a/tu/script/worker.php
Si tu aplicación PHP está incrustada en el binario, puedes agregar un Caddyfile personalizado en el directorio raíz de la aplicación.
Será usado automáticamente.
También es posible reiniciar el worker al detectar cambios en archivos con la opción --watch.
El siguiente comando activará un reinicio si algún archivo que termine en .php en el directorio /ruta/a/tu/app/ o sus subdirectorios es modificado:
frankenphp php-server --worker /ruta/a/tu/script/worker.php --watch="/ruta/a/tu/app/**/*.php"
Esta función se utiliza frecuentemente en combinación con hot reloading.
Tip
La siguiente sección es necesaria solo para versiones anteriores a Symfony 7.4, donde se introdujo soporte nativo para el modo worker de FrankenPHP.
El modo worker de FrankenPHP es soportado por el Componente Runtime de Symfony. Para iniciar cualquier aplicación Symfony en un worker, instala el paquete FrankenPHP de PHP Runtime:
composer require runtime/frankenphp-symfony
Inicia tu servidor de aplicación definiendo la variable de entorno APP_RUNTIME para usar el Runtime de FrankenPHP Symfony:
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
Consulta la documentación dedicada.
El siguiente ejemplo muestra cómo crear tu propio script de worker sin depender de una biblioteca de terceros:
<?php
// public/index.php
// Prevenir la terminación del script de worker cuando una conexión de cliente se interrumpe
ignore_user_abort(true);
// Iniciar tu aplicación
require __DIR__.'/vendor/autoload.php';
$myApp = new \App\Kernel();
$myApp->boot();
// Manejador fuera del bucle para mejor rendimiento (menos trabajo)
$handler = static function () use ($myApp) {
try {
// Llamado cuando se recibe una petición,
// las superglobales, php://input y similares se reinician
echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
} catch (\Throwable $exception) {
// `set_exception_handler` se llama solo cuando el script de worker termina,
// lo cual puede no ser lo que esperas, así que captura y maneja excepciones aquí
(new \MyCustomExceptionHandler)->handleException($exception);
}
};
$maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0);
for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests) {
$keepRunning = \frankenphp_handle_request($handler);
// Haz algo después de enviar la respuesta HTTP
$myApp->terminate();
// Llama al recolector de basura para reducir las posibilidades de que se active en medio de la generación de una página
gc_collect_cycles();
if (!$keepRunning) break;
}
// Limpieza
$myApp->shutdown();
Luego, inicia tu aplicación y usa la variable de entorno FRANKENPHP_CONFIG para configurar tu worker:
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 omisión, se inician 2 workers por CPU. También puedes configurar el número de workers a iniciar:
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
Como PHP no fue diseñado originalmente para procesos de larga duración, aún hay muchas bibliotecas y códigos heredados que generan fugas de memoria. Una solución para usar este tipo de código en modo worker es reiniciar el script de worker después de procesar un cierto número de peticiones:
El fragmento de worker anterior permite configurar un número máximo de peticiones a manejar estableciendo una variable de entorno llamada MAX_REQUESTS.
Aunque es posible reiniciar workers al detectar cambios en archivos, también es posible reiniciar todos los workers de manera controlada a través de la API de administración de Caddy. Si el admin está habilitado en tu Caddyfile, puedes activar el endpoint de reinicio con una simple petición POST como esta:
curl -X POST http://localhost:2019/frankenphp/workers/restart
Si un script de worker falla con un código de salida distinto de cero, FrankenPHP lo reiniciará con una estrategia de retroceso exponencial.
Si el script de worker permanece activo más tiempo que el último retroceso * 2,
no penalizará al script de worker y lo reiniciará nuevamente.
Sin embargo, si el script de worker continúa fallando con un código de salida distinto de cero en un corto período de tiempo
(por ejemplo, tener un error tipográfico en un script), FrankenPHP fallará con el error: too many consecutive failures.
El número de fallos consecutivos puede configurarse en tu Caddyfile con la opción max_consecutive_failures:
frankenphp {
worker {
# ...
max_consecutive_failures 10
}
}
Las superglobales de PHP ($_SERVER, $_ENV, $_GET…)
se comportan de la siguiente manera:
frankenphp_handle_request(), las superglobales contienen valores vinculados al script de worker en sífrankenphp_handle_request(), las superglobales contienen valores generados a partir de la petición HTTP procesada; cada llamada a frankenphp_handle_request() cambia los valores de las superglobalesPara acceder a las superglobales del script de worker dentro de la retrollamada, debes copiarlas e importar la copia en el ámbito de la retrollamada:
<?php
// Copia la superglobal $_SERVER del worker antes de la primera llamada a frankenphp_handle_request()
$workerServer = $_SERVER;
$handler = static function () use ($workerServer) {
var_dump($_SERVER); // $_SERVER vinculado a la petición
var_dump($workerServer); // $_SERVER del script de worker
};
// ...