【问题标题】:Get the PHP-FPM timeout limit in script获取脚本中的 PHP-FPM 超时限制
【发布时间】:2016-10-29 17:21:23
【问题描述】:

我正在使用 FPM 在 PHP 5.6.26 上开发一个 vagrant box。

我正在测试电池以通过一系列请求访问 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 中有设置,但我不想在我的脚本中硬编码该值,以防它发生变化。

【问题讨论】:

  • 如何监控脚本执行时间(使用哪些函数)?
  • @Zimmi function remaining() { return ini_get('max_execution_time') - ( time() - $_SERVER['REQUEST_TIME']); }

标签: php timeout


【解决方案1】:

简而言之,使用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'];
}

或者把它变成一个函数……

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 2011-11-02
    • 1970-01-01
    • 2018-02-20
    • 2011-08-27
    相关资源
    最近更新 更多