概述
RoadRunner 是一个高性能的PHP应用程序服务器和进程管理器,其设计考虑了通过使用插件的可扩展性。RoadRunner是由Golang开发的,它利用Golang的goroutine特性,提供了高并发的处理能力。这种能力使得RoadRunner非常适合用于处理高流量的Web应用程序,可以有效地应对高并发访问的情况。通过以 worker 的形式运行您的应用程序来运行,其中每个 worker 代表一个单独的进程,从而确保其操作的隔离性和独立性。
它被设计为 PHP 应用程序的中央处理器,帮助开发人员轻松创建更快、响应更快且更健壮的应用程序。
特点和优势
高性能:利用Golang的goroutine特性,RoadRunner具有极高的并发处理能力。这意味着它可以同时处理大量的请求,从而提高应用程序的性能。 支持HTTP/2:RoadRunner支持HTTP/2协议,该协议提供了多路复用、流量控制和加密等特性,进一步提高了应用程序的性能和安全性。 扩展性:RoadRunner支持扩展,可以根据项目的需求定制和扩展其功能。这使得开发人员可以根据具体的应用场景,定制和优化RoadRunner以满足特定的需求。 跨平台:RoadRunner可以在不同的操作系统上运行,如Windows、Linux和Mac OS等。这使得开发人员可以根据自己的需求选择合适的操作系统来部署应用程序。 队列支持:RoadRunner支持队列,可以有效地处理异步任务和后台任务。这有助于提高应用程序的响应速度和吞吐量。 易于安装:RoadRunner提供了简单的安装方式,使得开发人员可以快速地部署应用程序。同时,它还提供了详细的文档和示例,帮助开发人员快速上手和使用。
如何工作
RoadRunner 可以有效地管理一组 PHP 进程(称为 worker),并将来自各种插件的传入请求路由到这些 worker。此通信是通过 goridge 协议完成的,使您的 PHP 应用程序能够处理请求并将响应发送回客户端。
RoadRunner VS Nginx+FPM
PHP服务器
传统CGI协议服务器
客户端访问某个URL地址之后,通过 GET/POST/PUT
等方式提交数据,并通过HTTP协议向Web服务器发出请求,服务器端将HTTP请求里描述的信息通过标准输入(stdin)和环境变量(environment variable)传递给新建的CGI进程。处理完成后,进程立即关闭。
Nginx + PHP-FPM模式
现在流行的PHP web程序一般都是运行在Nginx + PHP-FPM
模式下的。PHP-FPM就是PHP对FastCGI的实现。
master创建并监听多个worker进程,通过共享内存获取worker的状态,进而通过信号控制worker进程。每一个worker进程就类似一个CGI进程,收到CGI请求后会执行相应的PHP文件,并把请求内容作为PHP进程状态的一部分(_GET, _POST, _SERVER
等等)。结束请求后,worker不会立刻结束,而是继续留在worker pool
. 这就节省了频繁创建结束子进程的开支。
RoadRunner
现在很多PHP的企业级框架都要求你加载至少十几个文件,构造多个类并解析一些配置,以便处理简单的用户请求或查询数据库。每个任务完成后,你不得不抛弃这些代码。收到下一个HTTP请求时,PHP-FPM会创建一个新的PHP子进程来处理这个请求,所有的文件都要重新加载一遍,即便文件可以有缓存,所有的代码也要重新运行。如果我们可以避免对每个请求都重启一次PHP子进程,我们就可以节约很多的资源。
RoadRunner可以看作一个升级版的Nginx + PHP-FPM. 它直接把长时运行的PHP进程作为worker, 直接对PHP worker进行监控和维护,每次收到http请求时,就发给php worker来处理。这样,我们就不再需要对每个请求重启一遍PHP了。
快速入门
安装 RoadRunner
获取最新版本的 RoadRunner 的最简单方法是下载一个预构建的版本二进制文件,这些二进制文件可用于各种操作系统,包括 macOS、Linux、FreeBSD 和 Windows。您可以在 GitHub 版本页面上找到这些二进制文件。
要安装 RoadRunner,只需从发布页面下载相应的存档并将其解压缩到您想要的应用程序目录中
Composer安装
如果您使用 Composer 来管理 PHP 依赖项,则可以安装 spiral/roadrunner-cli 包,以将最新版本的 RoadRunner 下载到项目的根目录。
composer require spiral/roadrunner-cli
运行以下命令以下载最新版本的 RoadRunner
./vendor/bin/rr get-binary
Server 二进制文件将位于项目的根目录中。
创建简单 worker
要创建 HTTP worker,您需要安装所需的 composer 包
composer require spiral/roadrunner-http nyholm/psr7
安装所需的软件包后,您可以创建一个 worker。以下是 PSR-7 服务器 API 的最简单入口。创建一个简单的 worker。创建一个名为 psr-worker.php
的新文件,并将以下内容添加到该文件中:
<?php /**
* @desc psr-worker.php 描述信息
* @author Tinywan(ShaoBo Wan)
*/ declare(strict_types=1); require __DIR__ . '/vendor/autoload.php'; use Nyholm\Psr7\Response; use Nyholm\Psr7\Factory\Psr17Factory; use Spiral\RoadRunner\Worker; use Spiral\RoadRunner\Http\PSR7Worker; // Create new RoadRunner worker from global environment $worker = Worker::create(); // Create common PSR-17 HTTP factory $factory = new Psr17Factory();
$psr7 = new PSR7Worker($worker, $factory, $factory, $factory); while (true) {
try {
$request = $psr7->waitRequest();
if ($request === null) {
break;
}
} catch (\Throwable $e) {
// Although the PSR-17 specification clearly states that there can be // no exceptions when creating a request, however, some implementations // may violate this rule. Therefore, it is recommended to process the // incoming request for errors. // // Send "Bad Request" response. $psr7->respond(new Response(400));
continue;
}
try {
// Here is where the call to your application code will be located. // For example: // $response = $app->send($request); // // Reply by the 200 OK response $psr7->respond(new Response(200, [], 'Hello RoadRunner! 【开源技术小栈】'));
} catch (\Throwable $e) {
// In case of any exceptions in the application code, you should handle // them and inform the client about the presence of a server error. // // Reply by the 500 Internal Server Error response $psr7->respond(new Response(500, [], 'Something Went Wrong!'));
// Additionally, we can inform the RoadRunner that the processing // of the request failed. Use error instead of response to indicate // worker error, do not use both. // $psr7->getWorker()->error((string)$e); }
}
此工作程序希望通过标准管道与 RoadRunner 服务器进行通信。
配置文件
接下来,您需要为 RR 创建一个简单的配置文件。打开文本编辑器并创建一个名为 .rr.yaml
的新文件。将以下内容添加到文件中:
server: command: "php psr-worker.php" http: address: 0.0.0.0:8282 # do not use development mode in production logs: level: debug mode: development
启动服务器
现在您可以启动服务器。当前文件夹中应包含以下文件:
.rr.yaml
文件psr-worker.php
文件RoadRunner 二进制 rr
然后,打开当前文件夹中的终端窗口并运行以下命令:
./rr serve
由于处于开发模式,因此您应该会看到以下输出:
2024-11-23T12:51:26+0000 DEBUG server worker is allocated {"pid": 451, "max_execs": 0, "internal_event_name": "EventWorkerConstruct"} 2024-11-23T12:51:26+0000 DEBUG server worker is allocated {"pid": 452, "max_execs": 0, "internal_event_name": "EventWorkerConstruct"}
[INFO] RoadRunner server started; version: 2024.2.1, buildtime: 2024-09-12T16:25:04+0000 [INFO] sdnotify: not notified 2024-11-23T12:51:26+0000 DEBUG http http server was started {"address": "0.0.0.0:8282"} 2024-11-23T12:51:30+0000 DEBUG server req-resp mode {"pid": 451} 2024-11-23T12:51:30+0000 INFO http http log {"status": 200, "method": "GET", "URI": "/", "URL": "/", "remote_address": "172.18.0.1:51278", "read_bytes": 0, "write_bytes": 42, "start": "2024-11-23T12:51:30+0000", "elapsed": 575} 2024-11-23T12:51:31+0000 DEBUG server req-resp mode {"pid": 452} 2024-11-23T12:51:31+0000 INFO http http log {"status": 200, "method": "GET", "URI": "/favicon.ico", "URL": "/favicon.ico", "remote_address": "172.18.0.1:51278", "read_bytes": 0, "write_bytes": 42, "start": "2024-11-23T12:51:30+0000", "elapsed": 550}
访问服务
服务地址:http://127.0.0.1:8282/