高并发状态下,error_log 偶尔出现:
upstream timed out (110: Connection timed out) while reading response header from upstream
因为是偶尔出现这个 time out, 我自己访问又没有任何问题,所以不知道该怎么排查,是 upstream 服务器请求太多处理不过来?还是反代服务器和 upstream 服务器网络连接有问题,还是反代服务器 nginx 配置问题?
so 上给出的最高赞答案: https://stackoverflow.com/questions/18740635/nginx-upstream-timed-out-110-connection-timed-out-while-reading-response-hea 把 proxy_read_timeout 加大就可以了,感觉完全是治标不治本啊
nginx 能不能设置一个超过 time out 就自动再向 upstream 服务器重新发送请求的功能?
|  |      1seers      2022-09-30 08:37:55 +08:00 proxy_next_upstream 配置看看 | 
|      2justest123      2022-09-30 08:57:49 +08:00  1 以前学 Nginx 的时候收藏的一篇博客[TCP SOCKET 中 backlog 参数的用途是什么?]( https://www.cnxct.com/something-about-phpfpm-s-backlog/),其中提到过上游服务 backlog 过大的情况下,可能来不及处理,导致 Nginx 超时报 110 (提一个思路,不一定是这个问题 | 
|  |      3picone      2022-09-30 08:57:50 +08:00  9 首先要理解这个错误,请求分 3 个阶段,连接,写,读,这个错误意思是读的时候超时了。那错误本身就是从 upstream 读取请求结果超时。我认为的排查方向: - 找到下游服务对应的日志,看看请求处理时间是多少。经验来说这个问题可能性最大,需要下游增加处理请求超时。 - 网络问题,下游返回回包了,上游没接到,看一下网络 IO 是不是打满了,看一下 TCP 重传的指标。 - 超时重试有 proxy_next_upstream ,但是注意幂等请求。https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream | 
|      4qoo2019      2022-09-30 09:00:02 +08:00 proxy_next_upstream error timeout http_500; | 
|      5julyclyde      2022-09-30 09:26:22 +08:00 应该是上游处理能力满了 nginx 到上游的连接,在上游的处理能力以外,但还在 backlog 范围内 上游内核会先接受 tcp 连接,等实际服务的程序调用 accept 获得这个链接 | 
|  |      6redford42      2022-09-30 09:29:32 +08:00 可以看一下服务器的 tcp 链接是否有丢弃请求的情况 | 
|  |      7zliea      2022-09-30 09:56:29 +08:00 upstream 用 keepalive 了么? | 
|  |      8zliea      2022-09-30 09:57:27 +08:00 还需要看是否需要调整后端服务器的连接数。 | 
|      9facelezz      2022-09-30 10:40:51 +08:00 @picone 是的 既然都是 reading timeout 那出错的方向 肯定在 nginx 和你的服务上 1.检查 I/O 2.带宽 3.检测丢包情况 4.你的服务偶尔超时 5.proxy_read_timeout 过小(严格上来讲还是属于 4 ) 楼上提到的 proxy_next_upstream 可以让 ng 在这个情况下 重试下一个 upstream 里的节点 经验来说 4 可能性最大,连接数我觉得不需要调整,毕竟是 reading timeout (已经连上了) | 
|      10facelezz      2022-09-30 10:42:04 +08:00 不过 4 的话 你们有 APM 的话 应该很容易发现吧 | 
|  |      11lambdaq      2022-09-30 10:53:24 +08:00 二楼 @justest123  的回答是对的。就是你代码处理不过来排队了,后面的请求一看卧槽排这么长的队就 gg 了。 | 
|  |      12lambdaq      2022-09-30 10:55:07 +08:00 有一个思路是 nginx 请求的时候带上一个头比如 proxy_set_header x-nginx-time $time_iso8601; 然后你在代码接到请求里对比一下,看下别人请求在排队的时候蹲了多长时间。 | 
|      13facelezz      2022-09-30 11:14:16 +08:00  1 @lambdaq 那也不对吧 backlog 过大是 Connection timed out 过小是 Connection refused 题主的报错不是 reading timeout 么 | 
|      14julyclyde      2022-09-30 12:11:32 +08:00 @facelezz backlog 过大的话是可以建立连接的 建立连接和 backlog 是内核处理的。user space 的是 accept 从已经建立的连接们取一个回来 | 
|  |      15kisshere OP @facelezz 那请问一下,怎么查看当前 Nginx 默认的 proxy_read_timeout 呢?谢谢 | 
|  |      16lambdaq      2022-09-30 13:33:10 +08:00 @facelezz  backlog  过大,已经连上的比如有 1000 个,但是都过了 60s 没能得到 accept(),那么 nginx 还是会 upstream timed out 的。 upstream 其实很多时候压根不知道 nginx 已经放弃请求了,还在那里吭哧吭哧挨个处理队列呢。。。 | 
|      17facelezz      2022-09-30 13:41:01 +08:00 | 
|      18julyclyde      2022-09-30 13:41:50 +08:00 @facelezz reading timeout 就是 exactly 这个问题 如果把 backlog 设小一点,早就失败然后下一个了 | 
|  |      20kisshere OP @picone 下游服务对应的 error_log 日志只记录了 host 和 referer 还有请求网址,没有处理时间啊? | 
|  |      21kisshere OP @facelezz 查了下默认超时是 60s ,话说你愿意等待一个网页加载超过 60s 么?大多数人等个三四秒没反应就关闭网页了,这个超时时间加长和没加长又有什么区别。。。 | 
|  |      22picone      2022-09-30 14:03:03 +08:00 @lambdaq  查了一下 nginx 的 backlog 的配置文档: sets the backlog parameter in the listen() call that limits the maximum length for the queue of pending connections. By default, backlog is set to -1 on FreeBSD, DragonFly BSD, and macOS, and to 511 on other platforms. 这个 backlog 也就是 listen 队列的长度。其实调整这个感觉是治标不治本,相当于更多需要 accept 的连接都没被处理到,如果都 accept 了就是往 upstream 建立更多的连接。upstream 其实是能指定 nginx 放弃请求的,TCP 会 FIN ,对应比如 Go 里面就是 context canceled 。 定位错误的另外一个方法是开启 debug 级别的日志观察一下。 | 
|  |      23picone      2022-09-30 14:05:20 +08:00 @kisshere 下游服务也是 nginx 服务? 可以查一下下游的 access_log ,如果是对应的请求有 499 的话基本实锤是下游服务的问题了。 感觉你们的日志并没有串起来,建议在最上游的服务搞一个 logid/traceid 之类含义的字段,放 header ,然后全链路都透传这个字段,查日志就能一一对应了。 | 
|  |      24lambdaq      2022-09-30 14:05:53 +08:00 @picone  这里说的不是 nginx 的 backlog 。说的是响应 nginx 请求的 upstream 的 backlog 。 | 
|      26facelezz      2022-09-30 14:13:19 +08:00 我感觉这个少了 APM 和日志链 并不好排查 可以按照上面的提示调整下 backlog 或者配置 proxy_next_upstream 来缓解 | 
|      27dusu      2022-09-30 22:14:57 +08:00 via iPhone 1. Accesslog 里把 upstream_response_time 写上 2. 自己写个 bash 统计上游平均响应时长 3. ss -s 看看系统连接情况 4. ss -tlnp 看 backlog 占用情况 | 
|      29julyclyde      2022-10-08 11:45:38 +08:00 你把 upstream server address 记录下来看看,有些请求可能会有好几个 upstream server address |