ReactPHP真正的异步吗?

38

我最近在测试ReactPHP,因为它看起来非常棒。我已经使用以下react/socket的代码进行了测试,用于创建一个简单的Socket服务器。

$loop = React\EventLoop\Factory::create();

$socket = new React\Socket\Server($loop);
$socket->on('connection', function ($conn) {
    echo 'New client !';

    $conn->on('data', function ($data) use ($conn) {
        $conn->write("Wow, some data, such cool\n");
        $conn->close();
    });
});
$socket->listen(1337);

$loop->run();

到目前为止还没有问题。当一个客户端连接时,服务器会显示New client !并且客户端会接收到响应。

但我进行了一项新的测试,在data事件上进行更多的处理。为了说明我的话,我将添加一个for循环,需要几毫秒才能完成:

$conn->on('data', function ($data) use ($conn) {
    $conn->write("Wow, some data, such cool\n");

    for ($i=0; $i<10000000; $i++); // here

    $conn->close();
});

在这种情况下,有10个客户端,当所有客户端处理完毕(大约2秒)后,客户端将显示文本Wow, some data, such cool,但服务器将立即显示New client !,无需等待。

所以这里我的理解不够,ReactPHP是一个异步I/O库,但是PHP是单线程的,如果在输入和输出之间存在大量处理,那么会阻塞所有客户端。


https://dev59.com/xnVD5IYBdhLWcg3wJIEK#15501449 - moonwave99
1
我并不是在问PHP是否支持多线程,我正在另一个项目中使用https://github.com/krakjoe/pthreads,但是简而言之,我想知道我是否已经达到了这个库的限制。 - Divi
2
这个库基本上是围绕着 stream_socket_server 进行封装的,就我所知。问题是 stream_socket_server 是否是异步的。考虑到 PHP 的基本架构,这让我感到惊讶,但我不知道确切的答案。 - deceze
你可以使用stream_set_blocking(stream, true or false)来设置非阻塞套接字服务器。 - Divi
当然可以,但是这只影响像fgets()和fread()这样从流中读取数据的调用。在非阻塞模式下,fgets()调用总是会立即返回,而在阻塞模式下,它将等待数据在流中变得可用。这并没有涉及异步处理的内容... - deceze
1个回答

56
ReactPHP 是一种异步 I/O 技术,但 PHP 是单线程的,如果在输入和输出之间有大量处理,则会阻塞所有客户端。
ReactPHP 非常受 node.js 的启发,遵循相同的原则。这种基于事件的模式的目标不是利用您服务器的 16 个 CPU,而是通过在控制器暂停请求 A 的同时,处理 HTTP 请求 B,直到“数据库请求成功”事件被调用才继续执行请求 A 的控制器来充分利用您的处理器。
您的测试正好与 node.js 和 ReactPHP 所做的假设相反:“计算速度快,I/O 速度慢”,所以如果我们在 I/O 期间(而不是在 I/O 之间)进行计算,则 CPU 时间将始终以比所需更高的数量可用。
使用 node.js 或 ReactPHP 如果您想使用服务器的 16 个 CPU,则只需在 16 端口上启动 16 个服务器进程,并在它们前面加上像 nginx 这样的负载平衡器。
但请记住,ReactPHP 仍然处于实验阶段,尚未准备好用于生产。

2
Kraken或Swoole呢?它们也是实验性的吗?它们与amphp有什么不同? - Gregory Magarshak
你应该观看这个视频并自行决定。v=fQxxm4vD8Ok - Robot70

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接