为什么Apache在200秒后返回零内容长度到PHP POST请求?

时间:2014-09-30 00:43:12

标签: php apache

我有PHP脚本将请求发布到远程API。如果响应时间超过大约200秒,那么我只会在响应中获得内容长度为零。我想弄清楚为什么会这样。

为了解决这个问题,我已经设置了Apache的所有可想到的变量和PHP的配置文件设置为超过300秒来解决这个问题,正如下面第一个答案所建议的那样。我设置为300秒的事情:

  • Apache超时
  • Apache keep_alive time
  • PHP max_reponse_time
  • PHP session.cache_expire time
  • PHP max_execution_time

尽管如此,我仍然始终在200秒左右的时间内获得零内容长度响应。但是,如果不到200秒,问题就不会发生。

下面我将介绍如何设置代码。

crontab在我们的服务器上运行shell脚本,使用/ usr / bin / curl调用localhost URI。 localhost URI由Apache提供,是一个PHP文件,它本身包含以下代码,而后者又使用cURL调用远程API。我们发布大约10KB的XML,期望以块的形式接收大约135KB。

以下是请求代码:

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->_xml_url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_VERBOSE, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_str);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $output = curl_exec($ch);        
        curl_close($ch);

我在Apache日志记录中启用了调试,下面是我们得到的。在此示例中,请求在19:48:00发送,响应在19:51:23发回,仅在200秒之后。

* About to connect() to api.asdf.com port 443 (#0)
*   Trying 555.555.555.555... * connected
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSL connection using RC4-SHA
* Server certificate:
*    subject: snip
*    start date: 2014-03-12 10:22:02 GMT
*    expire date: 2015-04-16 12:32:58 GMT
*    subjectAltName: api.asdf.com matched
*    issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign Organization Validation CA - G2
*    SSL certificate verify ok.
> POST /xmlservlet HTTP/1.1

Host: api.asdf.com
Accept: */*
Content-Type: text/xml
Content-Length: 10773
Expect: 100-continue

< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Type: text/xml
< Server: Microsoft-IIS/7.5
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Date: Thu, 06 Nov 2014 19:51:23 GMT
< Content-Length: 0
< 

* Connection #0 to host api.asdf.com left intact
* Closing connection #0

我想知道这段代码是否有问题,或者我可能在服务器设置中遗漏的内容可能导致内容长度在200秒后回归零。

5 个答案:

答案 0 :(得分:6)

听起来非常像远程API服务器上的超时 - 尝试手动访问它,例如通过浏览器或wget。

答案 1 :(得分:4)

  

并且是一个PHP文件,它本身包含以下代码,其中   反过来使用cURL调用远程API。我们POST约10KB   XML并期望以块的形式返回大约135KB。

     

以下是请求代码:

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $this->_xml_url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_str);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $output = curl_exec($ch);        
    curl_close($ch);

最有可能发生的是远程服务器($this->_xml_url)实际上是负载均衡器或其他前端块,其超时时间为200秒并调用后端服务器。

如果后端服务器没有在时间范围内应答,前端服务器将关闭后端连接并继续执行(这可能是错误的做法)并向您的脚本发送“成功“回答它的内容。

哪个没什么。因此内容长度为零。

您可以做的最好的事情是通过检查数据长度或XML一致性来识别问题,然后重试或通知用户。我使用的超时时间低于200秒 - 假设为180秒 - 以确保将是引发错误的那个,即远程服务器永远不会挂断你,会挂断

还尝试通知API服务器维护人员,以防有加速请求的方法(不同的API?不同的编码?缓存结果的可能性?更昂贵的SLA等等)

答案 2 :(得分:4)

您是否尝试过明确设置HTTP Keepalive?像这样的东西:

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Connection: Keep-Alive',
    'Keep-Alive: 300'
));

答案 3 :(得分:1)

您是否尝试在PHP中使用set_time_limit

http://php.net/manual/en/function.set-time-limit.php

php的默认值通常为30秒,可在php.ini

中找到

有关配置Apache的信息,请参阅timeoutkeepalivekeepalivetimeoutmaxkeepaliverequests

http://users.cis.fiu.edu/~downeyt/cgs4854/timeout


另请参阅http://www.devside.net/wamp-server/apache-and-php-limits-and-timeouts了解整体教程。

我已经能够用apache和php运行15分钟的请求了,所以你可以将它延长很长时间。

答案 4 :(得分:0)

确保使用您尝试访问的外部资源的完整URL路径(因为我们无法从您的代码示例中验证),更重要的是,请确保您的cron命令是从脚本的路径执行的住在这里,像这样:

1 1 * * 0 /path/to/your/script php < yourscript.php

这样做可以确保正确找到相对位置路径引用的任何内容。

请记住,当您通过浏览器测试某些内容时,您的apache日志很好,但由于您正在编写脚本,因此crontab相关错误将发送到您的cron输出文件。