Boot your application once and keep it in memory. FrankenPHP will handle incoming requests in a few milliseconds.
The worker mode of FrankenPHP is supported by the Symfony Runtime Component. To start any Symfony application in a worker, install the FrankenPHP package of PHP Runtime:
composer require runtime/frankenphp-symfony
Start your app server by defining the APP_RUNTIME
environment variable to use the 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 \
dunglas/frankenphp
See this Pull Request.
The following example shows how to create your own worker script without relying on a third-party library:
<?php
// public/index.php
// Boot your app
require __DIR__.'/vendor/autoload.php';
$myApp = new \App\Kernel();
$myApp->boot();
$nbRequests = 0;
do {
$handler = static function () use ($myApp) {
// Called when a request is received,
// superglobals, php://input and the like are reset
echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
};
$running = \frankenphp_handle_request($handler);
// Do something after sending the HTTP response
$myApp->terminate();
// Call the garbage collector to reduce the chances of it being triggered in the middle of a page generation
gc_collect_cycles();
} while ($running && !(isset($_SERVER['MAX_REQUESTS']) && ++$nbRequests >= $_SERVER['MAX_REQUESTS']));
// Cleanup
$myApp->shutdown();
Then, start your app and use the FRANKENPHP_CONFIG
environment variable to configure your worker:
docker run \
-e FRANKENPHP_CONFIG="worker ./public/index.php" \
-v $PWD:/app \
-p 80:80 -p 443:443 \
dunglas/frankenphp
By default, one worker per CPU is started. You can also configure the number of workers to start:
docker run \
-e FRANKENPHP_CONFIG="worker ./public/index.php 42" \
-v $PWD:/app \
-p 80:80 -p 443:443 \
dunglas/frankenphp
As PHP was not originally designed for long-running processes, there are still many libraries and legacy codes that leak memory. A workaround to using this type of code in worker mode is to restart the worker script after processing a certain number of requests:
The previous worker snippet allows configuring a maximum number of request to handle by setting an environment variable named MAX_REQUESTS
.