PHP cURL 随机超时,收到 100% 的正文

Posted

技术标签:

【中文标题】PHP cURL 随机超时,收到 100% 的正文【英文标题】:PHP cURL randomly timeouts with 100% of body received 【发布时间】:2020-02-11 17:12:26 【问题描述】:

我们有一个带有大约 50 个前端服务器的应用程序,其中包含 php 代码,通过使用 guzzle 库的 nginx 与 100 毫秒超时,总共 15-25k HTTP RPS 到 GO API 服务器。有时(随机,一天几次)我们会在 PHP 前端服务器日志中看到 500-10k RPS 失败并出现 curl 超时错误。日志中的所有异常如下所示:

cURL error 28: Operation timed out after 100 milliseconds with 143 out of 143 bytes received

最有趣的部分是它总是收到100% out of 100%字节,从来没有100 of 1020 of 70。所以 PHP 接收到完整的主体(我们对此很确定,因为当我们通过 CLI curl 重放这些请求时,它的大小总是等于失败的响应主体大小)。

当我们开始在 nginx-access 日志中跟踪这些超时请求时,我们看到,上游服务(Go API)在 1 毫秒(平均)内成功处理了每个请求,并由 nginx 毫无延迟地返回。 Nginx 访问日志:

GET [path] HTTP/1.1" 200 228 "-" [...] request_time: 0.001 upstream_addr: [addr] upstream_response_time: 0.001 upstream_status: 200

当我与我们的开发运维人员交谈时,nginx 已针对最大客户端(数百万个连接)进行了调整; Go 服务响应时间的第 99 个百分位

100ms超时可能是什么问题,在哪里挖掘解决?

UPD:

与客户端连接相关的NGINX配置:

worker_processes        32;
worker_rlimit_nofile    65535;

events 
    worker_connections      32767;
    accept_mutex on;


upstream [service] 
    server [main] max_fails=0;
    server [...] backup max_fails=0;
    keepalive 16;


location ^~ /[path]/ 
    proxy_pass http://[service]/;
    proxy_http_version 1.1;

    keepalive_timeout 30;
    keepalive_requests 500;

    reset_timedout_connection on;

    proxy_set_header Connection "";

转到 1.13 版。 net/http 用于服务客户。该服务没有外部依赖项(数据库、缓存等),它只是根据输入数据计算传入请求的哈希值。

PHP 7.2.0 版本使用guzzlehttp/guzzle@5.3.4 HTTP 客户端

【问题讨论】:

为什么会涉及到 Nginx? @Adrian 因为它被用作从公共客户端到内部 Go 服务的代理 + 负载均衡器。 Go 服务在 3 个实例上运行。 考虑到发生了多少,有很多潜在的故障点,从 Go 代码到 Nginx 配置,再到 PHP 代码,再到任何服务 PHP(nginx 中的 php-fpm ?)。没有看到就不可能说出来。 【参考方案1】:

在您的负载均衡器上,您应该在请求完成时强制关闭连接

backend nodes
  ...
  option forceclose
  ...

通过这样做,负载均衡器将在看到传输的响应时关闭连接

https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#option%20forceclose

【讨论】:

为什么?这个答案没有说明为什么会导致问题。 我们没有 haproxy 作为平衡器,只有 nginx

以上是关于PHP cURL 随机超时,收到 100% 的正文的主要内容,如果未能解决你的问题,请参考以下文章

php使用curl设置超时的重要性

PHP:默认 cURL 超时值

在PHP中设置Curl的超时

检查PHP curl请求是否已超时

PHP/Curl:在下载正文之前检查响应标头

PHP curl 上传大文件非常大慢,导致超时,小文件(10M以下)的还可以,请问如何解决啊!