ReactPHP HTTP Server Running Async



我想知道是否有一种方法可以让ReactPHP HTTP服务器异步处理请求。我使用文档(https://github.com/reactphp/http)设置了一个非常基本的HTTP服务器

HTTPServer.php

<?php
$httpServer = new ReactHttpServer(
function(PsrHttpMessageServerRequestInterface $request) {
$responseData = $request->getUri()->getPath();
if($responseData == "/testSlow") {sleep(5);} // simulate a slow response time
if($responseData == "/testFast") {sleep(1);} // simulate a fast response time
return new ReactHttpMessageResponse(
"200",
array("Access-Control-Allow-Headers" => "*", "Access-Control-Allow-Origin" => "*", "Content-Type" => "application/json"),
json_encode($responseData)
);
}
);
$socketServer = new ReactSocketServer("0.0.0.0:31");
$httpServer->listen($socketServer);
?>

它似乎工作得很好,但同步,如果我发送一个请求到/testSlow路径,然后立即到/testFast路径,慢的一个总是在5秒后先完成,只有一旦它完成了,快速的一个然后开始并在1秒后完成

我错过了一些额外的设置吗?

ReactPHP的事件循环异步处理请求,不并行. 这意味着只有一个进程在运行。并调用sleep()挂起该进程,即阻止事件循环处理下一个请求。因此,在异步应用程序中(在Node.js中也是如此),将繁重的处理转移到专用进程是一种常见的做法。

我不是ReactPHP专家,所以不能提供一个工作示例,但可以指出问题的根本原因。我建议大家阅读这个很棒的博客:https://sergeyzhuk.me/reactphp-series,尤其是这篇文章:https://sergeyzhuk.me/2018/05/04/reactphp-child-processes

ReactPHP使用EventLoop并在单线程PHP上工作。这意味着通过在代码中调用sleep(),您阻塞了主线程,因此EventLoop被阻塞,ReactPHP和PHP进程在睡眠期间不会做任何事情。你需要在事件循环中设置一个计时器,而不是使用sleep()

下面是重写的示例脚本:

<?php
$httpServer = new ReactHttpServer(
function(PsrHttpMessageServerRequestInterface $request) {
$responseData = $request->getUri()->getPath();
$timeout = 0;
if($responseData == "/testSlow") { // simulate a slow response time
$timeout = 5;
}
if($responseData == "/testFast") { // simulate a fast response time
$timeout = 1;
}
// create a promise that will resolve after $timeout seconds
$promise = new ReactPromisePromise(function ($resolve, $reject) use ($timeout) {
ReactEventLoopLoop::addTimer($timeout, function () use ($resolve) {
$resolve();
});
});
// when the promise is resolved, this callback will create the HTTP response
return $promise->then(function () use ($responseData) {
return new ReactHttpMessageResponse(
"200",
array("Access-Control-Allow-Headers" => "*", "Access-Control-Allow-Origin" => "*", "Content-Type" => "application/json"),
json_encode($responseData)
);
});
}
);
$socketServer = new ReactSocketServer("0.0.0.0:8080");
$httpServer->listen($socketServer);
?>

您可以在react/http库的官方文档中找到有关此主题的更多文档和示例,并在:https://github.com/reactphp/http#deferred-response.

希望这对你有帮助!

最新更新