PHP fsockopen通过浏览器连接超时,但不通过CLI

PHP fsockopen通过浏览器连接超时,但不通过CLI,php,curl,fsockopen,connection-timeout,command-line-interface,Php,Curl,Fsockopen,Connection Timeout,Command Line Interface,我正在与一个奇怪的问题作斗争,并且没有什么想法,希望这里的人能帮我解决。这是关于到外部服务器的随机连接超时—从浏览器运行时非常频繁,但从CLI运行时非常罕见。更多详细信息和代码: 在我的网站example.com上,我有一个表单。一旦用户提交HTTP POST,php就会向外部服务器发送另一个POST请求http://external.com/check.php 用一些POST数据。一旦得到响应,它将继续执行其余代码,并最终输出一个网页。看起来是这样的: if (!empty($_POST) {

我正在与一个奇怪的问题作斗争,并且没有什么想法,希望这里的人能帮我解决。这是关于到外部服务器的随机连接超时—从浏览器运行时非常频繁,但从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个连接超时错误

最奇怪的是,当我登录到生产服务器并通过CLI运行完全相同的代码片段时,只有0.1%的请求面临连接超时错误,99.9%的请求工作正常!即使我加入2000次迭代的循环,比率也保持不变

我和external.com的管理员谈过,他们说他们只有5%的服务器负载,他们的其他客户没有遇到任何超时问题,所以看起来这是我的php或网络问题

我的开发服务器和生产服务器的配置是相同的,唯一的区别是负载-生产中大约每秒150个请求。需要明确的是:这150个请求是我的访问用户,但不是每个请求都提交表单并打开套接字。每秒只有大约14个这样的用户,即每秒有大约14个帖子从我的服务器发送到external.com

当我试着用curl替换fsockopen时,它变得更好了——现在大约45%发送到external.com的帖子都是通过浏览器成功的——这仍然不能令人满意。当我从CLI运行时,它工作得非常好。错误消息略有不同,但实际上是相同的:无法连接到主机

你知道为什么通过浏览器发送的请求往往会失败,而通过CLI发送的请求工作正常吗

如果重要的话:我使用的是PHP5.3.27,我的Web服务器是Apache。当我通过浏览器调用phpinfo和通过CLI调用php-v时,版本号是相同的

提前感谢,

普斯特里克

*编辑*

结果是他们的路由器配置有问题

external.com的管理员没有看到任何负载增加,因为他们看到的是错误的机器。罪魁祸首是他们的路由器,而不是服务器external.com。 他们已经改变了路由器的配置,但没有透露具体的设置,我想我们永远也不会知道。有趣的是,既然他们已经解决了这个问题,现在同样的问题出现在我的开发服务器上。。。但这是我可以接受的。需要明确的是:在我这方面,开发服务器使用的路由器与生产服务器不同,但它们的配置是相同的,除了IP等。
我要感谢所有在这个问题上帮助我的人。显然我们无能为力。

也许您已经检查过了,但是php cli、mod_php dev、stage、live的配置真的相同吗?似乎配置了非常短的超时。这也解释了fsockopen和curl的不同行为,它们有不同的设置iirc


请看一看:在fsockopen的文档中,注意到超时仅用于打开套接字。

您的服务器是基于linux还是基于windows的?它是一个共享托管服务器或具有指定带宽的专用服务器?它基于linux,托管在我公司自己的数据中心。Bandwitdh非常宽泛,external.com返回的数据大小不到100个字符加上HTTP头。你说的是每秒150个请求。这是每分钟9000个请求。在不到7分钟的时间内,您将使用所有服务器套接字。您应该针对这种负载调整linux系统。此外,考虑保持生存连接和一个小守护进程来处理这种流量,您浪费了大量的网络资源。对不起,也许我不够清楚:它大约是每秒150次请求到我的服务器ExpRel.com,但不是每个访问用户提交一个表单并打开一个套接字。每秒只有大约14个请求从我的服务器发送到external.com。我将编辑原始问题以明确这一点。尝试将卷曲超时提高到60秒,看看会发生什么。curl_setopt$ch,CURLOPT_CONNECTTIMEOUT,60;curl_setopt$ch,CURLOPT_超时,60;是的,除了必须不同之外,所有这些配置文件都是相同的。中的第一个示例显示,我需要为已打开的连接设置超时,但在我的示例中,由于超时,连接无法打开;换句话说,w ords-它无法建立我可以设置超时的连接。