在脚本中获取PHP-FPM超时限制


Get the PHP-FPM timeout limit in script

我在PHP 5.6.26上使用FPM开发一个流浪盒子。

我正在做一个测试电池,用一系列请求击中REST端点,试图捕获远程端的间歇性错误。在我的电池中,我有一个变量来表示要运行的重复次数。因为我不知道每个请求需要多长时间,所以有时大量的重复会导致脚本超时,并且我将无法看到已经运行的请求的结果。

因此,我决定最大化测试运行次数,而不是指定重复次数。我监视脚本执行了多长时间,如果我们使用ini_get('max_execution_time')接近超时,就尝试保释。

然而,我注意到使用这种方法,我没有得到和以前一样多的测试运行。我做了更多的调试,发现可以超过max_execution_time!

我做了更多的调查,发现PHP-FPM有自己的超时限制,当我的脚本死亡时,我达到了这个限制:

[Fri Oct 28 19:41:04.491557 2016] [proxy_fcgi:error] [pid 2343:tid 140619049568000] (70007)The timeout specified has expired: [client 192.168.253.1:52431] AH01075: Error dispatching request to :, referer: http://local.mysite.com/test

所以,知道我想运行测试只要我允许,我如何得到实际的超时值从PHP-FPM在我的脚本?

我知道/etc/php-fpm.d/www.conf中有设置,但我不想在脚本中硬编码该值,以防它发生变化。

总之,用getrusage(),不要用time()

现在再多一点。受max_execution_time限制的脚本执行时间是在脚本内花费的时间。来自set_time_limit doc,第二条注释:

方法执行之外的活动所花费的时间脚本,例如使用system()的系统调用,流操作,在确定最大值时不包括数据库查询等脚本运行的时间。在Windows上不是这样其中测量时间为实数

最简单的例子:sleep(35)max_execution_time = 30是可以的,正如你已经注意到的。

如果您使用time(),您将总是在30秒后结束,即使您还有时间编写脚本。

所以你需要脚本中的实时时间,而不是真实世界的时间。为了得到这种时间,你有getrusage()函数和它的答案ru_utime.tv_secru_utime.tv_usec键。

第二步,当您使用PHP-FPM时,它是响应多个请求的相同进程。这意味着一个进程将这些ru_utime的统计信息从一个请求传递到另一个请求。您必须在脚本开始时获得ru_utime.tv_sec值并计算差异。当这个差值接近max_execution_time时,可以结束重复/循环。

例如:

$gru = getrusage();
$gru_start = $gru['ru_utime.tv_sec'];
$gru_end = $gru_start;
// Considering that duration of one iteration in
// the next while loop is less than 1 second,
// we use this as the max limit.
$max_time = ini_get('max_execution_time') - 1;
while ($gru_end - $gru_start < $max_time) {
    // long and repetitives tasks
    // ....
    // could use a counter to not call this function at each iteration,
    // but only once every 10, 100, 1000 ... times.
    $gru = getrusage();
    $gru_end = $gru['ru_utime.tv_sec'];
}

或者将其转化为函数…

希望它能带你走得更远。老实说,我在这里的理解有点有限,这个解决方案可能有点脆弱,请适当小心使用。