我在PHP CLI脚本中使用CURL库对服务器进行大量API调用。
我注意到在28,219个连接(顺序打开/执行,而不是同时)之后卷曲失败。每次尝试的后续请求都会在大约30秒后失败。
正在访问的API(据我所知)并未挂起或导致错误。我试图访问不同的远程主机,并且总是会发生错误,因此我怀疑问题出在PHP / Curl上,而不是远程主机。
这是我用来演示此问题的示例脚本:
try {
for ($i = 0; $i < 1000000; ++$i) {
get('https://example.org/'); // change me if you're going to run this
echo '.';
}
} catch (Exception $e) {
echo "Error happened on {$i} - {$e->getMessage()}";
}
function get($url) {
$curl = curl_init($url);
if (! $curl) {
throw new Exception('Error1 - Could not create new curl handle');
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 20);
$contents = curl_exec($curl);
$info = curl_getinfo($curl);
if ($errno = curl_errno($curl)) {
throw new Exception("Error2 " . curl_strerror($errno), $errno);
}
curl_close($curl);
if ($info['http_code'] === 200) {
return $contents;
}
throw new Exception("Error3", (int) $info['http_code']);
}
输出:
............................................... .................................................. .................................................. .................................................. .................................................. .................................................. ................................................发生错误在28219 - Error2无法连接到服务器
我倾向于认为这个错误正在发生,因为我已经耗尽了可用的TCP套接字,但我对如何知道这个问题的正确解决方案的工作方式还不够熟悉(简短)减少请求的数量。)
编辑:
由于人们一直建议将其作为远程服务器,因此围攻对我的测试服务器(带有API的服务器)执行1000000次请求的结果。我不是100%确定导致单一失败的原因,但它只发生过一次,因此我将其视为一种异常,不像我在28,219次请求后从CURL获得的一致失败。 / p>
siege -c 1 -r 1000000 http://mytestserver/same/url/as/with/curl
* SIEGE 3.0.5
** Preparing 1 concurrent users for battle.
The server is now under siege...
The server is now under siege...[error] socket: -187603200 connection refused.: Connection refused
done.
Transactions: 999999 hits
Availability: 100.00 %
Elapsed time: 626.70 secs
Data transferred: 7719.03 MB
Response time: 0.00 secs
Transaction rate: 1595.66 trans/sec
Throughput: 12.32 MB/sec
Concurrency: 0.94
Successful transactions: 999999
Failed transactions: 1
Longest transaction: 0.14
Shortest transaction: 0.00
答案 0 :(得分:2)
每次迭代都会创建一个新的curl资源。如果您重新使用连接,一切都应按预期工作。将curl初始化循环并传入curl变量