Guzzle send()方法导致cURL错误


Guzzle send() method causes cURL error 35 Too many open files

尝试使用Guzzle 5执行以下代码。

$client = new GuzzleClient(['defaults/headers/User-Agent' => static::$userAgentString]);
$request = $client->createRequest(static::$serviceRequestMethod, $url, $options); // Create signing request.
$signature = new Signature'Signature($this->accessKey, $this->secretKey);
$options = array_merge_recursive($options, ['query' => ['Signature' => $signature->signString($hash)]]);
$request = $client->createRequest(static::$serviceRequestMethod, $url, $options); // Create real request.
$response = $client->send($request);

当我在长时间运行的CLI进程中调用这行足够多次时,我得到以下错误,可以追溯到$response = $client->send($request);

cURL error 35: error:02001018:system library:fopen:Too many open files

点击后,服务器上的所有其他网页和命令都会崩溃,并出现同样的"打开的文件太多"错误。

下面是堆栈跟踪:

#0 /home/vagrant/code/example.com/vendor/guzzlehttp/guzzle/src/RequestFsm.php(104): GuzzleHttp'Exception'RequestException::wrapException(Object(GuzzleHttp'Message'Request), Object(GuzzleHttp'Ring'Exception'ConnectException))
#1 /home/vagrant/code/example.com/vendor/guzzlehttp/guzzle/src/RequestFsm.php(132): GuzzleHttp'RequestFsm->__invoke(Object(GuzzleHttp'Transaction))
#2 /home/vagrant/code/example.com/vendor/react/promise/src/FulfilledPromise.php(25): GuzzleHttp'RequestFsm->GuzzleHttp'{closure}(Array)
#3 /home/vagrant/code/example.com/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php(55): React'Promise'FulfilledPromise->then(Object(Closure), NULL, NULL)
#4 /home/vagrant/code/example.com/vendor/guzzlehttp/guzzle/src/Message/FutureResponse.php(43): GuzzleHttp'Ring'Future'CompletedFutureValue->then(Object(Closure), NULL, NULL)
#5 /home/vagrant/code/example.com/vendor/guzzlehttp/guzzle/src/RequestFsm.php(135): GuzzleHttp'Message'FutureResponse::proxy(Object(GuzzleHttp'Ring'Future'CompletedFutureArray), Object(Closure))
#6 /home/vagrant/code/example.com/vendor/guzzlehttp/guzzle/src/Client.php(165): GuzzleHttp'RequestFsm->__invoke(Object(GuzzleHttp'Transaction))
#7 /home/vagrant/code/example.com/app/library/amazon/src/AWS.php(540): GuzzleHttp'Client->send(Object(GuzzleHttp'Message'Request))

我不知道通过Guzzle发送请求后是否需要显式地关闭资源。是我遗漏了什么,还是这是Guzzle的bug ?

这不是Guzzle或MailGun的问题,而是库的特定实现的问题。有这么多长时间运行(打开)的请求,实际上已经达到底层操作系统(libcurl、openssl和fopen)的极限了。

根据libcurl errors error 35表示SSL/TLS握手出错

根据各种google参考error: 02001018表示openssl无法访问(或更确切地说是读取)证书文件。

您可以使用ulimit来查看和修改各种系统范围的资源限制。

您还可以使用lsof来查看打开的文件。

解决您的问题:

  1. (如果可以的话)增加系统资源允许量-务必研究此更改可能产生的影响。
  2. 重构你的代码,这样你就不会达到操作环境的限制。也许可以对某些请求使用异步通信。一个不同的库,或者"下拉"并实现你自己的库。
  3. 找到一些方法来实现某种类型的速率限制(我已将其与#2分开列出),但它们可以齐头并进。