cURL/PHP 请求执行时间为 50%
彻底搜索后,我无法理解为什么向启用 SSL 的远程主机发出的 cURL 请求在我的案例中只有 50% 左右的成功率。情况如下:我有一系列 cURL 请求,所有这些请求都在我使用 PHP CLI 运行的单个 PHP 脚本中发出到 HTTPS 远程主机。有时,当我运行脚本时,请求会成功执行,但由于某种原因,大多数时候我运行它时,我都会从 cURL 中收到以下错误:
* About to connect() to www.virginia.edu port 443 (#0)
* Trying 128.143.22.36... * connected
* Connected to www.virginia.edu (128.143.22.36) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac
* Closing connection #0
如果我再试几次,我会得到相同的结果,但经过几次尝试后,请求将成功通过。此后再次运行脚本会导致错误,并且该模式会继续。研究错误“alert bad record mac”并没有给我带来任何帮助,而且我犹豫是否将其归咎于 SSL 问题,因为该脚本仍然偶尔运行。
我使用的是 Ubuntu Server 10.04,安装了 php5 和 php5-curl,以及最新版本的 openssl。就 cURL 特定选项而言,CURLOPT_SSL_VERIFYPEER 设置为 false,CURLOPT_TIMEOUT 和 CURLOPT_CONNECTTIMEOUT 均设置为 4 秒。进一步说明此问题的事实是,在我的 Mac OS X 开发计算机上也发生了同样的情况 - 请求仅在约 50% 的时间内通过。
After searching all over, I can't understand why cURL requests issued to a remote SSL-enabled host are successful only 50% or so of the time in my case. Here's the situation: I have a sequence of cURL requests, all of them issued to a HTTPS remote host, within a single PHP script that I run using the PHP CLI. Occasionally when I run the script the requests execute successfully, but for some reason most of the times I run it I get the following error from cURL:
* About to connect() to www.virginia.edu port 443 (#0)
* Trying 128.143.22.36... * connected
* Connected to www.virginia.edu (128.143.22.36) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac
* Closing connection #0
If I try again a few times I get the same result, but then after a few tries the requests will go through successfully. Running the script after that again results in an error, and the pattern continues. Researching the error 'alert bad record mac' didn't give me anything helpful, and I hesitate to blame it on an SSL issue since the script still runs occasionally.
I'm on Ubuntu Server 10.04, with php5 and php5-curl installed, as well as the latest version of openssl. In terms of cURL specific options, CURLOPT_SSL_VERIFYPEER is set to false, and both CURLOPT_TIMEOUT and CURLOPT_CONNECTTIMEOUT are set to 4 seconds. Further illustrating this problem is the fact that the same exact situation occurs on my Mac OS X dev machine - the requests only go through ~50% of the time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
远程主机可能不是真正的唯一主机。也许这是某种负载平衡解决方案,其中多个服务器接受传入请求。
让我认为可能是错误消息中的“mac error”。这可能意味着在 SSL 协商仍在运行时远程主机 MAC 地址发生了变化。这可以解释为什么有时你没有任何问题。
但也许不是:-) SSL 问题很难发现。
我不明白你对 prefork MPM 与 Worker MPM 的回答,如果你在 cli 模式下运行 PHP,你的 apache MPM 不会被使用,你甚至没有使用 apache。
The remote host is maybe not a real unique host. Maybe it's some sort of load balancing solution with several servers taking the incoming requests.
What make me think it could be that is the 'mac error' in the error message. This could mean the remote host mac address as changed while the SSL negociation was still running. And this could explain that sometimes you do not have any problem.
But maybe not :-) SSL problems are quite hard to find.
I do not understand your answer on prefork MPM vs Worker MPM, if you run PHP in cli mode your apache MPM is not used, you're not even using apache.
您可能需要此选项:
CURLOPT_FORBID_REUSE
传递一个长整型。设置为 1 以使下一次传输完成后显式关闭连接。通常,libcurl 在完成一次传输后会保持所有连接处于活动状态,以防后续传输可以重新使用它们。应谨慎使用此选项,并且仅在您了解其用途时才使用。设置为 0 以使 libcurl 保持连接打开以供以后重新使用(默认行为)。
You may need this option:
CURLOPT_FORBID_REUSE
Pass a long. Set to 1 to make the next transfer explicitly close the connection when done. Normally, libcurl keeps all connections alive when done with one transfer in case a succeeding one follows that can re-use them. This option should be used with caution and only if you understand what it does. Set to 0 to have libcurl keep the connection open for possible later re-use (default behavior).
你尝试过吗?
curl_setopt($handle, CURLOPT_SSLVERSION, 3);
Had you tried?
curl_setopt($handle, CURLOPT_SSLVERSION, 3);