【问题标题】:Exhausting Curl's Sockets in PHP?用尽 PHP 中 Curl 的套接字?
【发布时间】:2016-06-11 19:11:04
【问题描述】:

我正在使用 PHP CLI 脚本中的 CURL 库对服务器进行大量 API 调用。

我注意到在 28,219 个连接(顺序打开/执行,而不是同时)之后 curl 失败。尝试的每个后续请求都会失败,直到大约 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 套接字,但我对它的工作原理不够熟悉,无法知道这个问题的正确解决方案(没有发出更少的请求)。

编辑:

由于人们一直建议它是远程服务器,因此这里是 siege 对我的测试服务器(具有 API 的服务器)执行 1000000 次请求的结果。我不能 100% 确定导致单次失败的原因,但它只发生了一次,所以我将其视为异常情况,这与我在 28,219 次请求后从 CURL 获得的持续失败不同。

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

【问题讨论】:

  • 请更详细地告诉我们您遇到了什么错误
  • 可能被屏蔽了——请求太多了,考虑加个 sleep 语句
  • @self 被什么阻止了?远程服务器没有阻止请求,我可以在它上面运行许多我正在做的请求,没有任何问题。
  • “无法连接到服务器”实际上表明服务器端拒绝了许多连接...如果 curl 本身会用完套接字,它可能会返回另一个错误
  • 嗯...,您可以在条件语句中设置计数,设置为您认为它会中断的某个(高)数字,然后退出?之后将该数字更改为更高的数字。我无法解决您的问题,但这就是我要尝试找出失败/停止需要多少次调用。 @伊恩

标签: php sockets curl


【解决方案1】:

您每次迭代都会创建一个新的 curl 资源。如果您重新使用连接,一切都应该按预期工作。将curl初始化出循环并传入curl变量

【讨论】:

  • 嗯,我没有意识到您可以多次重复使用 curl 句柄。我猜只有在 URL 不变的情况下才能做到这一点,对吧?
  • 支持保持活动请求的单个站点没有但有更多好处 curl_setopt($ch, CURLOPT_URL, "example.com");
猜你喜欢
  • 2016-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-09
  • 2016-02-18
  • 2018-10-13
  • 2011-01-19
  • 1970-01-01
相关资源
最近更新 更多