我有一个从第三方服务接收更新的无限循环。这个 while 循环是受监督的,这意味着如果它中断,脚本将自动重新启动。
while (true) {
try {
// Long polling requests to retrieve messages from the bot
} catch (BreakLoopException $exception) {
break;
}
}
但是,我遇到了一个问题,即 while 循环有时会冻结。我怀疑这可能是由于内存泄漏造成的。因此,我调整了方法,决定在单独的进程中运行长轮询逻辑,如下所示:
$round = 0;
while ($round < 100) {
exec("php " . base_path() . "/artisan bot:get-updates");
$round++;
}
此外,我确保 while 循环在 100 轮后自动中断,因此主管将重新启动它。尽管进行了这些更改,脚本仍然冻结,即使 while 循环应该只运行 100 次。
截至目前,距离上次脚本重启已经过去了 24 小时,这很不寻常。
为什么会出现这种情况?
看起来您的外部程序
exec("php " . base_path() . "/artisan bot:get-updates");
冻结了。我建议使用 PHP 进程来更好地控制执行(包括在发生超时时杀死外部进程)。
为了测试,我使用了 operation.php
<?php
echo 'TEST01' . PHP_EOL;
sleep(5);
echo 'TEST02' . PHP_EOL;
并用以下方式调用它:
<?php
$command = 'php operation.php';
$timeout = 0.1; // Timeout in seconds
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
for($i=0; $i<100; $i++) {
$process = proc_open($command, $descriptorspec, $pipes);
if(is_resource($process)) {
$starttime = microtime(true);
while(proc_get_status($process)['running']) {
if((microtime(true)-$starttime) > $timeout) {
proc_terminate($process);
break;
}
usleep(10000); // Sleep for 10 ms
}
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$exit_code = proc_close($process);
echo 'OUTPUT: ' . $stdout . PHP_EOL;
}
usleep(10000); // Sleep for 10 ms
}
它将输出
TEST01
但永远不会输出 TEST02
,除非 $timeout
是 >5
。