我正在解决一个奇怪的问题并且没有想法,希望有人可以帮助我。它是关于外部服务器的随机连接超时 - 从浏览器运行时非常频繁,但从CLI运行时非常罕见。更多细节和代码:
在我的网站example.com
我有一张表格。一旦用户提交它(HTTP POST),php就会向一个带有一些POST数据的外部服务器http://external.com/check.php
发送一个请求(另一个POST)。一旦得到响应,它继续执行其余代码并最终输出一个网页。它看起来像这样:
if (!empty($_POST) {
// here goes some POST validation stuff, and then:
req = http_build_query($_POST);
$http_request = "POST /check.php HTTP/1.0\r\n";
$http_request .= "Host: external.com\r\n";
$http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
$http_request .= "Content-Length: " . strlen($req) . "\r\n";
$http_request .= "User-Agent: SpeciallyDefinedForExternal.com/PHP\r\n";
$http_request .= "\r\n";
$http_request .= $req;
}
if (false == ($fs = fsockopen($host, $port, $errno, $errstr, 10))) {
throw new Exception($errstr, $errno);
}
fwrite($fs, $http_request);
while (!feof($fs)) {
$response .= fgets($fs, 1024); // One TCP-IP packet
}
fclose($fs);
// do some stuff depending on on $response
当我在开发服务器上运行它时,一切正常,但是一旦我将它部署到生产环境,它会随机地在fsockopen()
调用时抛出异常。
我在日志文件中检查过大约15%的fsockopen()
来电是成功的,其余的是110 Connection timed out
错误。
最奇怪的是,当我登录到生产服务器并通过CLI运行相同的代码片段时,只有0.1%的请求面临连接超时错误,99.9%的工作完美!即使我在2000次迭代的循环中输入,该比率保持不变。
我与external.com
的管理员交谈,他们说他们只有5%的服务器负载,而他们的其他客户没有遇到任何超时问题,所以看起来这是我的php或网络问题。< / p>
我的开发服务器和生产服务器的配置完全相同,唯一的区别是负载 - 生产中每秒约150个请求。要明确:这150个请求是我的访问用户,但不是每个请求都提交表单并打开套接字。每秒只有大约14个这样的用户,即每秒大约有14个POST从我的服务器发送到external.com
。
当我尝试将fsockopen()
替换为curl
时,它变得更好 - 现在发送到external.com
的约有45%的POST成功(通过浏览器) - 这仍然不能令人满意。当我从CLI运行时 - 它完美无缺。并且错误消息略有不同,但实际上意味着相同:couldn't connect to host
。
任何想法可能是什么原因,通过浏览器的请求往往会失败,而那些通过CLI发送的请求可以正常工作?
如果重要:我使用的是php 5.3.27,我的网络服务器是Apache。当我通过浏览器呼叫phpinfo()
而通过CLI呼叫php -v
时,版本号是相同的。
提前致谢,
Pstryk
*编辑*
结果证明路由器配置存在问题。
external.com
的管理员没有看到任何负载增加,因为他们正在查看错误的计算机。罪魁祸首是他们的路由器,而不是服务器external.com
。
他们改变了路由器配置中的一些东西,但是没有透露它究竟是什么设置,我想我们永远都不会知道。有趣的是,既然他们已经解决了这个问题,现在我的开发服务器上出现了同样的问题...但这是我可以忍受的。需要说明的是:就我而言,开发服务器使用的路由器与生产服务器不同,但它们的配置相同(除了IP等)。
我要感谢所有试图帮助我解决这个问题的人。显然,我们无能为力。
答案 0 :(得分:0)
也许你已经检查了但是php-cli,mod_php(dev,stage,live)的配置真的相同吗?似乎配置了非常短的超时。这也可以解释fsockopen和curl的不同行为,它们有不同的设置。
请查看:fsockopen文档中的http://php.net/stream_set_timeout注意到超时仅用于打开套接字。