【问题标题】:file_get_contents 1 minute timeout for https?file_get_contents https 的 1 分钟超时?
【发布时间】:2015-12-17 09:27:21
【问题描述】:

在通过 https 访问某些资源时,我遇到了 PHP 的 file_get_contents 挂起 60 秒的问题。

我不确定是客户端问题还是服务器端问题。

在客户端

在命令行上工作:

$ URL="https://example.com/some/path"
$ wget "$URL" -O /dev/null -q # takes a few milliseconds
$ curl "$URL" >/dev/null      # takes a few milliseconds
$ php -r 'file_get_contents("'"$URL"'")' # takes 61s!

在服务器上

立即将一行写入 Apache (2.4) 访问日志以获得正确的 SSL vhost,并返回 200(成功)响应。这是一个令人困惑的时间表:

  • 0s php 的 file_get_contents 在客户端触发
  • 0.2s 服务器的 apache 访问日志记录成功 (200)。
  • ???谁知道这里发生了什么???
  • 60.2s客户端收到文件。

从 Ubuntu 14.04 和 Debian 8 客户端测试。有问题的资源都在 Debian 8 服务器上,运行 Apache 2.4 和 ITK worker 和 PHP 5.6。我已经在关闭防火墙的情况下尝试过(默认接受策略),所以不是这样。 NB。服务器禁用了 IPv6,这可能与我注意到当某些东西首先尝试 IPv6 时出现这样的超时有关。但是被访问的主机没有 AAAA 记录,并且 apache 日志显示 (a) SSL 建立成功,并且 (b) 请求有效并被接收。

【问题讨论】:

    标签: php apache file-get-contents


    【解决方案1】:

    一个可能的答案:您确定客户端仅在 60.2 秒后收到文件吗?如果我没记错的话,file_get_contents() 有一个讨厌的习惯,就是在它认为请求完成之前等待远程连接关闭。这意味着,如果您的服务器使用 HTTP 保持活动状态,即在所有数据传输完成后有效地保持连接一段时间,您的应用程序可能会出现挂起。

    这样有帮助吗?

    $context = stream_context_create(['http' => ['header' => 'Connection: close\r\n']]);
    file_get_contents("https://example.com/some/path", false, $context);
    

    注意:您可能需要使用“https”作为该数组中的键;我不记得了。

    【讨论】:

    • 感谢您的建议,但这些建议和 https 都不起作用 - 结果相同。另外,服务器上的keepalive只有5s,所以我认为它必须是别的东西。非常感谢您抽出宝贵时间,非常感谢!
    • 那么像 Wireshark 这样的东西可以在一秒钟左右后看到 PHP 的连接关闭?
    • 嗯。我不是理解wireshark捕获的专家。但看起来加密的应用程序数据在一秒钟左右后收到,然后客户端发送ACK。在 http 版本上,我想我看到了一个 FIN 正在发送。 ?
    • 在这种情况下,我发现 Charles Proxy 比 Wireshark 更易于使用,特别是如果您安装了中间证书,以便它可以在加密请求中达到峰值。 Charles 不是免费的,但它确实有试用版——也许看看这是否有帮助?
    【解决方案2】:

    尝试跟踪脚本 php -r 'file_get_contents("'"$URL"'")' & 将在后台运行脚本并显示脚本 pid。而不是strace -p %pid%

    【讨论】:

    • 更好strace php -r 'file_get_contents("'"$URL"'");'
    • 谢谢。我不确定我在输出中寻找什么。我可以看到 read...= 1635 和 1635 是我正在获取的东西的长度。然后下一个read 得到一个EAGAIN,然后它转到pollevents=POLLIN|POLLPRI,这就是60 秒后的超时时间。 ?
    • poll 等待来自连接的事件,所以连接没有关闭并且 file_get_contents 想要更多的东西:) 60s - 是超时(default_socket_timeout)
    【解决方案3】:

    感谢答案让我更深入!

    这似乎是使用 ITK Apache MPM worker 的错误/怪癖。

    • 该模块出现此问题(file_get_contents 未关闭连接)。

    • 没有这个模块问题就解决了。

    自从升级到 Debian Jessie / Apache 2.4 以来,这不是我在该模块中发现的第一个错误。我会尽力举报的。

    啊哈!我是正确的。它是a bug,并且发布了一个修复程序,目前在 Debian jessie 中提出了更新。

    【讨论】:

      猜你喜欢
      • 2022-11-10
      • 2017-09-26
      • 2019-01-06
      • 2014-09-02
      • 2012-04-28
      • 1970-01-01
      • 2015-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多