【问题标题】:PHP Fatal error: Uncaught GuzzleHttp\Exception\RequestException: cURL error 2: easy handle already used in multi handlePHP 致命错误:未捕获的 GuzzleHttp\Exception\RequestException:cURL 错误 2:简单句柄已在多句柄中使用
【发布时间】:2020-04-18 06:29:22
【问题描述】:

我是用户而不是开发人员。开发者不可用。

这是 Google 购物产品提交脚本中使用的 Google API 库。

脚本每 20 分钟成功运行 2 年 + 昨天的前 5 个小时。

然后出现以下错误:

[18-Apr-2020 06:20:03 Europe/London] PHP Fatal error:  Uncaught GuzzleHttp\Exception\RequestException: cURL error 2: easy handle already used in multi handle (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) in ../vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:162
Stack trace:
#0 ../vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(129): GuzzleHttp\Handler\CurlFactory::createRejection(Object(GuzzleHttp\Handler\EasyHandle), Array)
#1 ../vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(89): GuzzleHttp\Handler\CurlFactory::finishError(Object(GuzzleHttp\Handler\CurlHandler), Object(GuzzleHttp\Handler\EasyHandle), Object(GuzzleHttp\Handler\CurlFactory))
#2 ../vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php(43): GuzzleHttp\Handler\CurlFactory::finish(ThObject(GuzzleHttp\Handler\CurlHandler), Object(GuzzleHttp\Handler\EasyHandle), Object(GuzzleHttp\Handler\CurlFactory))
#3 ../vendor/guzzlehttp/guzzle/src/Handl in ../vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php on line 162

在脚本停止工作时唯一的服务器变化是应用到物理主机的安全补丁和服务器重启。

PHP v7.3.16

我相信正在使用的 Google 库是 v2.0

我可以按照说明进行操作,但可能听不懂!

TIA

【问题讨论】:

  • 在谷歌搜索时找到this very recent WP site's thread,如果有帮助的话。
  • 谢谢,但我在那里看不到任何解决方案
  • 您尝试过什么调试问题?您使用的是这些库的哪个版本? v2.0 太旧了,可能需要更新一下?
  • @Nico Haase 前段时间我尝试将库更新到 v2.1,但它破坏了脚本。正如我所说,我是用户而不是开发人员,所以我恢复到 v2.0 并且一切都很好,直到现在。

标签: php curl libcurl google-shopping-api


【解决方案1】:

以防万一读到这篇文章的人正在使用 Laravel。几天前我们突然开始遇到同样的问题,尝试安装不同的 cURL 版本并设置 cURL 选项,但没有任何效果。我通过更改 vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php 文件来修复它。寻找写着的那一行

if (count($this->handles) >= $this->maxHandles) {
curl_close($resource);
} else {
...
}

全部注释掉,而不是 if/else 直接写

curl_close($resource);

换句话说,无论句柄数是多少,您总是关闭 cURL 连接。这对我们立即起作用!

希望对你有帮助:)

【讨论】:

  • 你节省了我的时间。谢谢。
  • 一般不建议更改vendor目录中的文件,所以我认为这应该算是一个hotfix :)
  • @Mark 绝对同意是的,这应该被视为临时修复:) 我已经用尽了我能想到的所有其他可能性,所以现在这是我可以让它工作的唯一方法.
  • @Matt 谢谢。这对我有用。即使看起来版本更改确实发生了(2 天),但问题再次出现。还没有发现服务器上发生了什么变化,但不管是什么,都没有改变 cURL 版本。
  • 这个解决方案解决了这个问题,但是更改供应商目录不是一个好主意。
【解决方案2】:

我们昨天和 Stripe 工程师一起解决了这个问题(这并不是说您的问题与 Stripe 相关,不是,但问题/解决方案应该是相同的)

(这些发现并非 100% 得到证实,但似乎是模式):它是在通过 cURL 发出 2 次以上请求时引起的,并且似乎发生在 cURL 的最新版本之一或至少一些其他软件(其中可能已自动更新或由您的托管服务提供商完成)

我们提供的解决方案是禁用 cURL 中的持久连接。根据您的实施,有不同的方法可以做到这一点。但是为了获得灵感,这就是我们使用 Stripe 的方式:

$curl = new \Stripe\HttpClient\CurlClient();
$curl->setEnablePersistentConnections(false);
\Stripe\ApiRequestor::setHttpClient($curl);

我想对于您的图书馆来说,这将与此类似。对于那些希望为 Stripe 解决这个问题的人来说,这里是:)

注意:这个解决方案理论上会对延迟产生影响,但是我们在实践中还没有遇到过这种情况。但是现在提到了:)

【讨论】:

  • 我使用 curl 7.69.1 并降级到 7.19.7 没有任何区别。已更改回 7.69.1。有没有你知道没有问题的版本?
  • 如果那是合适的文件,有人可以将修复应用到文件“CurlFactory.php”吗?如果是这样,我如何提供访问权限或将内容粘贴到此处?
  • @AspiEd 不幸的是,我们不知道哪个版本可能有用,并且仍然猜测 cURL 是罪魁祸首。它可能是另一个软件组件。但根据所有报道,这似乎是某种更新。但这是我们和 Stripe 团队的猜测。我们在 cURL 中禁用了持久连接以解决该问题。
  • 我已经恢复到 curl 7.69.1 并且一切都很好。现在,我已经从 yum 中删除了 curl + libcurl,所以它们不会更新。感谢您的帮助和建议。
【解决方案3】:

我已经恢复到 curl 7.69.1 并且一切都很好。 现在,我已经从 yum 中删除了 curl + libcurl,所以它们不会更新。 感谢您的帮助和建议,如果我的风格不正确,我们深表歉意。

【讨论】:

  • 过去 2 天我使用的是 v7.69.1,但同样的问题再次出现。
【解决方案4】:

public_html/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php

请在此 fn 中评论这些行

公共静态函数 wrapSync( 可调用 $default, 可调用 $sync ) {

    // return function (RequestInterface $request, array $options) use ($default, $sync) {
    //     return empty($options[RequestOptions::SYNCHRONOUS])
    //         ? $default($request, $options)
    //         : $sync($request, $options);
    // };

}

【讨论】:

    【解决方案5】:

    我没有使用 guzzle,但我在使用其他库时遇到了同样的问题

    php 7.4.6

    卷曲 7.19.7

    CentOS 6.10 版(最终版)

    包“mercadopago/dx-php”:“2.0.0”

    在我的开发服务器和我测试过的其他服务器上运行良好

    我不是 100%,但我认为这是 curl 库上的一个错误,它不允许为多个请求重用相同的 curl 连接(我再次不确定)。

    我用 mercadopago/dx-php 上的修补程序解决了这个问题,我编辑了 ./vendor/mercadopago/dx-php/src/MercadoPago/RestClient.php

    替换第 150 行

    来自 $connect = $this->getHttpRequest();

    到 $connect = new Http\CurlRequest();

    换句话说,强制为下一个请求使用新连接。在您的代码中查看重用连接的位置并尝试创建新连接。

    我知道,这很糟糕,因为: - 是第三方的修补程序 - 不能重复使用相同的连接

    但它奏效了。希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2021-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      • 2015-01-04
      • 1970-01-01
      相关资源
      最近更新 更多