密集的PHP脚本失败w /“指定的超时已过期”错误/ ap_content_length_filter

时间:2010-01-13 06:17:57

标签: php

运行失败的MySQL密集型PHP脚本。 Apache日志报告:

[Wed Jan 13 00:20:10 2010] [error] [client xxx.xx.xxx.xxxx] (70007)
The timeout specified has expired:
ap_content_length_filter: apr_bucket_read() failed,
referer: http://domain.com/script.php

尝试将set_time_limit(0)置于顶部。

还尝试set_time_limit(0)

既没有修复超时。

我可以在http.conf(或其他地方)设置一些特定的超时限制以防止这种情况发生吗?

10 个答案:

答案 0 :(得分:7)

我使用 Apache 2.4.6 PHP 5.4.23 FPM / FastCGI 打了一个非常相似的墙。

症状:

无论我在PHP或Apache中设置什么,我的脚本都会在30秒后超时,我会在Apache错误日志中看到以下内容:

  

[timestamp] [proxy_fcgi:error] [pid...] (70007)The timeout specified has expired: [client ...] AH01075: Error dispatching request to :

我的VirtualHost:

TimeOut  300
KeepAliveTimeout 300

<IfModule reqtimeout_module>
  RequestReadTimeout header=120-240,minrate=500
  RequestReadTimeout body=120,minrate=500
</IfModule>

<IfModule mod_proxy.c>
  ProxyTimeout 300
</IfModule>

<IfModule mod_fcgid.c>
  FcgidConnectTimeout 300
</IfModule>

讨厌的php脚本:

ini_set( 'max_execution_time', '120' );
...
ini_restore( 'max_execution_time' );

修复:它是Apache mod_proxy_fcgi

中的硬编码值
  

<强> Take a look at the bug report here

  • 补丁可用(上面的链接)
  • 该修复程序似乎尚未定为一般发布(2014年3月)

答案 1 :(得分:5)

首先,我的解决方案仅适用于Apache Web Server。

我正在编写一个脚本,用作针对非常大的数据库的报告的csv下载脚本,我也遇到了这个问题。不是使用php,而是我的脚本用一种名为heitml的晦涩语言编写; - )

请求超时问题确实发生在我的场景中,如下所示:

[Wed Sep 19 20:29:01 2012] [warn] [client ::1] Timeout waiting for output from CGI script /var/www/cgi-bin/heitml
[Wed Sep 19 20:29:01 2012] [error] [client ::1] (70007)The timeout specified has expired: ap_content_length_filter: apr_bucket_read() failed

我目前唯一可以适应的严肃解决方案是使用此官方超时配置扩展程序:mod_reqtimeout。它允许调整超时参数,例如:

允许10秒钟接收包括标题的请求,以及30秒接收请求正文:

RequestReadTimeout header=10 body=30

至少等待10秒钟才能收到请求正文。如果客户端发送数据,则每收到1000个字节,超时时间增加1秒,超时没有上限(由LimitRequestBody间接给出的限制):

RequestReadTimeout body=10,MinRate=1000

至少需要10秒钟才能收到包含标题的请求。如果客户端发送数据,则每收到500字节将超时时间增加1秒。但请求包括标题不允许超过30秒:

RequestReadTimeout header=10-30,MinRate=500

通常,服务器应配置标头和正文超时。如果http和https虚拟主机使用通用配置,则超时不应设置得太低:

RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500

尚未发现Apache是​​否提供了一个更好的解决方案,它不需要我使用这个模块(假设它没有默认安装 - 尽管它包含在2.2.15及更高版本的所有版本中)。 / p>

答案 2 :(得分:4)

我怀疑我得到了同样的错误,为更高版本的Apache(2.4.16)更新了:

Timeout 900

我想知道为什么在php.ini中增加max_execution_time并不起作用。

对我来说,修复只是增加了httpd.conf中的Timeout指令 https://httpd.apache.org/docs/2.4/mod/core.html#timeout

WHM

(或Apache Configuration - &gt; Global Configuration - &gt; str_extract,视具体情况而定)

此超时适用于IO事件之间的时间。因此,即使脚本几乎立即输出数据,脚本执行过程中的长时间延迟也会导致超时。

答案 3 :(得分:3)

还有php max_execution_time指令。请注意,Web服务器的超时设置也可能限制您的脚本:

  

您的网络服务器可能有其他超时   可能也会中断的配置   PHP执行。 Apache有一个超时   指令和IIS有一个CGI超时   功能。两者都默认为300秒。   请参阅您的Web服务器文档   具体细节。

实际上,这看起来像是一个Apache错误,它也会影响Python脚本。你试过googling it yet?

吗?

答案 4 :(得分:1)

还有一个超时值不在php本身,而是在apache服务器中。如果在指定时间内没有任何输出,它将制动脚本,因此当在PHP中进行更难的工作时,您可以达到此限制。只需回显浏览器(不是缓冲区!)或将apache超时值增加到安全值,据我记得它是KeepAliveTimeOut apache属性。祝你好运:)

答案 5 :(得分:0)

php.ini也有超时。

答案 6 :(得分:0)

我在php.ini中使用这些资源限制来解决问题。

max_execution_time = 300
max_input_time = 300
memory_limit = -1

答案 7 :(得分:0)

注意:此答案从similar question逐字复制。

Original Answer

我有Apache 2.4.6,但修复它的patch在Apache&gt; = 2.4.8中提供。 这里的关键是立即启动输出,以便Apache(mod_proxy_fcgi)认为连接是活动的。

例如,我正在使用PHP并且我的AJAX调用的数据库查询需要&gt; 30秒。 因为我知道整体响应将是&#34; Content-Type:application / json&#34;,我立即发送该标题。

#1: Start output immediately
#Note: Sending the header is innocuous
#   it can be changed later using the $replace parameter
#   (see #3)
header( 'Content-Type: application/json' );

#2: Run slow query
mysql_query( "SELECT * FROM giant_table" );

#3: Change header as needed
header( 'Content-Type: application/csv', true );

#output content

答案 8 :(得分:0)

我尝试了所有建议,但问题出在 php-fpm配置中。我在php-fpm配置文件中设置了以下行:

request_terminate_timeout = 300s

答案 9 :(得分:0)

对于可能遇到此问题的任何人。我可以通过查看内存缓存来解决此问题。

我的情况:

  1. 由多个apache服务器使用的内存缓存服务器
  2. memcached.sess_locking =开启
  3. 在同一会话中(在彼此之间的毫秒内)进行背对背请求

结果: 第二个请求陷入困境并超时

解决方案1: 在您的php.ini中设置memcached.sess_locking = Off

解决方案2: 减少memcached.sess_lock_wait_min

为什么起作用: 当第一个请求已锁定会话文件时出现第二个请求时,第二个会话必须等待。如果将memcached.sess_lock_wait_min设置得太高,它会等待很长时间才尝试拥有该锁。使用sess_locking = Off进行测试非常容易。如果它确实对您有帮助,那么您肯定想尝试一下锁定时间值,看看哪种方法更适合您。