使用 Supervisor 解决 php 无限循环脚本中的冻结问题

问题描述 投票:0回答:1

我有一个从第三方服务接收更新的无限循环。这个 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 小时,这很不寻常。

为什么会出现这种情况?

php supervisord
1个回答
0
投票

看起来您的外部程序

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

© www.soinside.com 2019 - 2024. All rights reserved.