优雅地关闭 ReactPhp 应用程序
Gracefully close ReactPhp app
这个问题与 Consume only N messages from RabbitMQ with react\stomp, ack them separately and then exit 非常相关,但更笼统。
例如,我有一个缓慢的 I/O 操作:
$port = 4000;
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$socket->on('connection', function ($conn) use ($loop){
$conn->on('data', function ($data) use ($conn, $loop) {
if ($data == 42) {
// this instantly stop the loop
$loop->stop();
}
$process = new React\ChildProcess\Process('sleep 5; echo ' . $data);
$loop->addTimer(0.001, function($timer) use ($process, $conn) {
$process->start($timer->getLoop());
$process->stdout->on('data', function($output) use ($conn) {
if ($output) {
$conn->write("> $output");
}
});
});
});
});
echo "Socket server listening on port $port.\n";
echo "You can connect to it by running: telnet localhost $port\n";
$socket->listen($port);
$loop->run();
echo "exited";
当我 运行 $loop->run();
我想在某个时候停止它,例如通过计时器,在接受 N 个请求后,或任何其他事件,如 pcntl_signal
,或数据断言,如示例中所示。
挑战是在退出前完成所有开始的工作,我不知道如何实现它。
在我的服务器控制台中:
Socket server listening on port 4000.
You can connect to it by running: telnet localhost 4000
exited
在我的客户端控制台中:
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
1
2
3
4
5
> 1
> 2
42
Connection closed by foreign host.
其中 1、2、3、4、5 以 1 秒的间隔输入
相反,我希望看到这样的内容:
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
1
2
3
4
5
> 1
> 2
42
> 3
6
> 4
> 5
Connection closed by foreign host.
如评论中所述,要正常退出,您需要跟踪 运行 进程并仅在所有进程完成时停止循环:
$socket->on('connection', function ($conn) use ($loop) {
$processes = new SplObjectStorage();
$stop = false;
$conn->on('data', function ($data) use ($conn, $loop, $processes, &$stop) {
if ('42' === trim($data)) {
$stop = true;
if (!$processes->count()) {
$loop->stop();
}
}
if ($stop) {
return;
}
$process = new React\ChildProcess\Process('sleep 5; echo ' . $data);
$processes->attach($process);
$process->on('exit', function () use ($process, $processes, &$stop, $loop) {
$processes->detach($process);
if ($stop && !$processes->count()) {
$loop->stop();
}
});
$loop->addTimer(0.001, function($timer) use ($process, $conn) {
$process->start($timer->getLoop());
$process->stdout->on('data', function($output) use ($conn) {
if ($output && '42' !== trim($output)) {
$conn->write("> $output");
}
});
});
});
});
这个问题与 Consume only N messages from RabbitMQ with react\stomp, ack them separately and then exit 非常相关,但更笼统。
例如,我有一个缓慢的 I/O 操作:
$port = 4000;
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$socket->on('connection', function ($conn) use ($loop){
$conn->on('data', function ($data) use ($conn, $loop) {
if ($data == 42) {
// this instantly stop the loop
$loop->stop();
}
$process = new React\ChildProcess\Process('sleep 5; echo ' . $data);
$loop->addTimer(0.001, function($timer) use ($process, $conn) {
$process->start($timer->getLoop());
$process->stdout->on('data', function($output) use ($conn) {
if ($output) {
$conn->write("> $output");
}
});
});
});
});
echo "Socket server listening on port $port.\n";
echo "You can connect to it by running: telnet localhost $port\n";
$socket->listen($port);
$loop->run();
echo "exited";
当我 运行 $loop->run();
我想在某个时候停止它,例如通过计时器,在接受 N 个请求后,或任何其他事件,如 pcntl_signal
,或数据断言,如示例中所示。
挑战是在退出前完成所有开始的工作,我不知道如何实现它。
在我的服务器控制台中:
Socket server listening on port 4000.
You can connect to it by running: telnet localhost 4000
exited
在我的客户端控制台中:
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
1
2
3
4
5
> 1
> 2
42
Connection closed by foreign host.
其中 1、2、3、4、5 以 1 秒的间隔输入
相反,我希望看到这样的内容:
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
1
2
3
4
5
> 1
> 2
42
> 3
6
> 4
> 5
Connection closed by foreign host.
如评论中所述,要正常退出,您需要跟踪 运行 进程并仅在所有进程完成时停止循环:
$socket->on('connection', function ($conn) use ($loop) {
$processes = new SplObjectStorage();
$stop = false;
$conn->on('data', function ($data) use ($conn, $loop, $processes, &$stop) {
if ('42' === trim($data)) {
$stop = true;
if (!$processes->count()) {
$loop->stop();
}
}
if ($stop) {
return;
}
$process = new React\ChildProcess\Process('sleep 5; echo ' . $data);
$processes->attach($process);
$process->on('exit', function () use ($process, $processes, &$stop, $loop) {
$processes->detach($process);
if ($stop && !$processes->count()) {
$loop->stop();
}
});
$loop->addTimer(0.001, function($timer) use ($process, $conn) {
$process->start($timer->getLoop());
$process->stdout->on('data', function($output) use ($conn) {
if ($output && '42' !== trim($output)) {
$conn->write("> $output");
}
});
});
});
});