From bd031a66f5baca214e7a6caaaf8a112b33e6adbb Mon Sep 17 00:00:00 2001 From: AMPHP Bot Date: Fri, 29 Dec 2023 10:50:55 -0600 Subject: [PATCH] Sync cluster.md --- cluster.md | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 cluster.md diff --git a/cluster.md b/cluster.md new file mode 100644 index 0000000..8cbe839 --- /dev/null +++ b/cluster.md @@ -0,0 +1,107 @@ +--- +notice: 'This file is imported and can be edited at https://github.com/amphp/cluster/blob/2.x/README.md' +title: '# Usage' +description: 'Learn how to create multiprocess server clusters.' +image: undraw/undraw_server_cluster.svg +permalink: /cluster +source: 'https://github.com/amphp/cluster/blob/2.x/README.md' +layout: docs +--- +

+cluster +

+ +This package provides tools to run multiple PHP processes that can listen on the same port, such as multiple [HTTP server](https://github.com/amphp/http-server) instances listening on the same port. Port-sharing is achieved with `SO_REUSEPORT` where available and socket transfers otherwise. + +Additionally, this package provides a mechanism to gracefully restart such processes with zero downtime. The entire cluster may be manually restarted or failed workers will automatically be respawned by the cluster watcher process. + + +Instead of starting the processes with `php server.php`, cluster-enabled applications are started with `php vendor/bin/cluster server.php`. + +A graceful restart can be initiated by sending a `USR1` signal to the cluster process. + +Cluster-enabled applications need only replace a few components with those provided by this package. + +#### Creating a Server + +`Amp\Socket\Server::listen()` is usually used to create an instance of `Amp\Socket\Server` for accepting client connections. + +Instead, `Amp\Cluster\Cluster::listen()` returns a promise that resolves to an instance of `Amp\Socket\Server`. `Cluster::listen()` allows addresses and ports to be shared across multiple PHP processes (or threads). + +#### Logging + +Log entries may be send to the cluster watcher to be logged to a single stream by using `Amp\Cluster\Cluster::createLogHandler()`. This handler can be attached to a `Monolog\Logger` instance. + +#### Process Termination + +Often signals are used to gracefully shutdown a server when a `SIGTERM` signal is received by the process. Instead of `Amp\Loop::onSignal()`, cluster-enable applications should use `Amp\Cluster\Cluster::onTerminate()` to define functions that handle graceful shutdown when `SIGINT` or `SIGTERM` is received. + +#### Hot Reload in IntelliJ / PHPStorm + +IntelliJ's file watchers can be used as trigger to send the `USR1` signal to the cluster's watcher process automatically on every file save. +You need to write a PID file using `--pid-file /path/to/file.pid` when starting the cluster and then setup a file watcher in the settings using the following settings: + + - Program: `bash` + - Arguments: `-c "if test -f ~/test-cluster.pid; then kill -10 $(cat ~/test-cluster.pid); fi"` + +## Example HTTP Server + +The example below (which can be found in the [examples](https://github.com/amphp/cluster/tree/master/examples) directory as [simple-http-server.php](https://github.com/amphp/cluster/blob/master/examples/simple-http-server.php)) uses [`amphp/http-server`](https://github.com/amphp/http-server) to create an HTTP server that can be run in any number of processes simultaneously. + +```php +setFormatter(new ConsoleFormatter); + } + + $logger = new Logger('worker-' . Cluster::getContextId()); + $logger->pushHandler($handler); + + // Set up a simple request handler. + $server = new Server($sockets, new CallableRequestHandler(function (Request $request): Response { + return new Response(Status::OK, [ + "content-type" => "text/plain; charset=utf-8" + ], "Hello, World!"); + }), $logger); + + // Start the HTTP server + yield $server->start(); + + // Stop the server when the worker is terminated. + Cluster::onTerminate(function () use ($server): Promise { + return $server->stop(); + }); +}); +```