nginx 反代高并发时,偶尔出现 upstream timed out 该怎么排查原因?

2022-09-30 08:34:14 +08:00
 kisshere

高并发状态下,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 服务器重新发送请求的功能?

4017 次点击
所在节点    程序员
29 条回复
seers
2022-09-30 08:37:55 +08:00
proxy_next_upstream 配置看看
justest123
2022-09-30 08:57:49 +08:00
以前学 Nginx 的时候收藏的一篇博客[TCP SOCKET 中 backlog 参数的用途是什么?]( https://www.cnxct.com/something-about-phpfpm-s-backlog/),其中提到过上游服务 backlog 过大的情况下,可能来不及处理,导致 Nginx 超时报 110 (提一个思路,不一定是这个问题
picone
2022-09-30 08:57:50 +08:00
首先要理解这个错误,请求分 3 个阶段,连接,写,读,这个错误意思是读的时候超时了。那错误本身就是从 upstream 读取请求结果超时。我认为的排查方向:
- 找到下游服务对应的日志,看看请求处理时间是多少。经验来说这个问题可能性最大,需要下游增加处理请求超时。
- 网络问题,下游返回回包了,上游没接到,看一下网络 IO 是不是打满了,看一下 TCP 重传的指标。
- 超时重试有 proxy_next_upstream ,但是注意幂等请求。https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream
qoo2019
2022-09-30 09:00:02 +08:00
proxy_next_upstream error timeout http_500;
julyclyde
2022-09-30 09:26:22 +08:00
应该是上游处理能力满了
nginx 到上游的连接,在上游的处理能力以外,但还在 backlog 范围内
上游内核会先接受 tcp 连接,等实际服务的程序调用 accept 获得这个链接
redford42
2022-09-30 09:29:32 +08:00
可以看一下服务器的 tcp 链接是否有丢弃请求的情况
zliea
2022-09-30 09:56:29 +08:00
upstream 用 keepalive 了么?
zliea
2022-09-30 09:57:27 +08:00
还需要看是否需要调整后端服务器的连接数。
facelezz
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 (已经连上了)
facelezz
2022-09-30 10:42:04 +08:00
不过 4 的话 你们有 APM 的话 应该很容易发现吧
lambdaq
2022-09-30 10:53:24 +08:00
二楼 @justest123 的回答是对的。就是你代码处理不过来排队了,后面的请求一看卧槽排这么长的队就 gg 了。
lambdaq
2022-09-30 10:55:07 +08:00
有一个思路是 nginx 请求的时候带上一个头比如 proxy_set_header x-nginx-time $time_iso8601;

然后你在代码接到请求里对比一下,看下别人请求在排队的时候蹲了多长时间。
facelezz
2022-09-30 11:14:16 +08:00
@lambdaq 那也不对吧 backlog 过大是 Connection timed out 过小是 Connection refused 题主的报错不是 reading timeout 么
julyclyde
2022-09-30 12:11:32 +08:00
@facelezz backlog 过大的话是可以建立连接的
建立连接和 backlog 是内核处理的。user space 的是 accept 从已经建立的连接们取一个回来
kisshere
2022-09-30 13:11:47 +08:00
@facelezz 那请问一下,怎么查看当前 Nginx 默认的 proxy_read_timeout 呢?谢谢
lambdaq
2022-09-30 13:33:10 +08:00
@facelezz backlog 过大,已经连上的比如有 1000 个,但是都过了 60s 没能得到 accept(),那么 nginx 还是会 upstream timed out 的。

upstream 其实很多时候压根不知道 nginx 已经放弃请求了,还在那里吭哧吭哧挨个处理队列呢。。。
facelezz
2022-09-30 13:41:01 +08:00
@julyclyde
@lambdaq
这就超出我知道的知识了,只是感觉 reading timeout 看上去不像是这个问题

@kisshere 默认好像是 60s 可以 Google 下
julyclyde
2022-09-30 13:41:50 +08:00
@facelezz reading timeout 就是 exactly 这个问题
如果把 backlog 设小一点,早就失败然后下一个了
facelezz
2022-09-30 13:44:55 +08:00
@julyclyde 这样吗 学到了~
kisshere
2022-09-30 13:52:07 +08:00
@picone 下游服务对应的 error_log 日志只记录了 host 和 referer 还有请求网址,没有处理时间啊?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/883940

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX