高并发状态下,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 服务器重新发送请求的功能?
1
seers 2022-09-30 08:37:55 +08:00
proxy_next_upstream 配置看看
|
2
justest123 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 (提一个思路,不一定是这个问题
|
3
picone 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 |
4
qoo2019 2022-09-30 09:00:02 +08:00
proxy_next_upstream error timeout http_500;
|
5
julyclyde 2022-09-30 09:26:22 +08:00
应该是上游处理能力满了
nginx 到上游的连接,在上游的处理能力以外,但还在 backlog 范围内 上游内核会先接受 tcp 连接,等实际服务的程序调用 accept 获得这个链接 |
6
redford42 2022-09-30 09:29:32 +08:00
可以看一下服务器的 tcp 链接是否有丢弃请求的情况
|
7
zliea 2022-09-30 09:56:29 +08:00
upstream 用 keepalive 了么?
|
8
zliea 2022-09-30 09:57:27 +08:00
还需要看是否需要调整后端服务器的连接数。
|
9
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 (已经连上了) |
10
facelezz 2022-09-30 10:42:04 +08:00
不过 4 的话 你们有 APM 的话 应该很容易发现吧
|
11
lambdaq 2022-09-30 10:53:24 +08:00
二楼 @justest123 的回答是对的。就是你代码处理不过来排队了,后面的请求一看卧槽排这么长的队就 gg 了。
|
12
lambdaq 2022-09-30 10:55:07 +08:00
有一个思路是 nginx 请求的时候带上一个头比如 proxy_set_header x-nginx-time $time_iso8601;
然后你在代码接到请求里对比一下,看下别人请求在排队的时候蹲了多长时间。 |
13
facelezz 2022-09-30 11:14:16 +08:00 1
@lambdaq 那也不对吧 backlog 过大是 Connection timed out 过小是 Connection refused 题主的报错不是 reading timeout 么
|
14
julyclyde 2022-09-30 12:11:32 +08:00
@facelezz backlog 过大的话是可以建立连接的
建立连接和 backlog 是内核处理的。user space 的是 accept 从已经建立的连接们取一个回来 |
15
kisshere OP @facelezz 那请问一下,怎么查看当前 Nginx 默认的 proxy_read_timeout 呢?谢谢
|
16
lambdaq 2022-09-30 13:33:10 +08:00
@facelezz backlog 过大,已经连上的比如有 1000 个,但是都过了 60s 没能得到 accept(),那么 nginx 还是会 upstream timed out 的。
upstream 其实很多时候压根不知道 nginx 已经放弃请求了,还在那里吭哧吭哧挨个处理队列呢。。。 |
17
facelezz 2022-09-30 13:41:01 +08:00
|
18
julyclyde 2022-09-30 13:41:50 +08:00
@facelezz reading timeout 就是 exactly 这个问题
如果把 backlog 设小一点,早就失败然后下一个了 |
20
kisshere OP @picone 下游服务对应的 error_log 日志只记录了 host 和 referer 还有请求网址,没有处理时间啊?
|
21
kisshere OP @facelezz 查了下默认超时是 60s ,话说你愿意等待一个网页加载超过 60s 么?大多数人等个三四秒没反应就关闭网页了,这个超时时间加长和没加长又有什么区别。。。
|
22
picone 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 级别的日志观察一下。 |
23
picone 2022-09-30 14:05:20 +08:00
@kisshere 下游服务也是 nginx 服务? 可以查一下下游的 access_log ,如果是对应的请求有 499 的话基本实锤是下游服务的问题了。
感觉你们的日志并没有串起来,建议在最上游的服务搞一个 logid/traceid 之类含义的字段,放 header ,然后全链路都透传这个字段,查日志就能一一对应了。 |
24
lambdaq 2022-09-30 14:05:53 +08:00
@picone 这里说的不是 nginx 的 backlog 。说的是响应 nginx 请求的 upstream 的 backlog 。
|
26
facelezz 2022-09-30 14:13:19 +08:00
我感觉这个少了 APM 和日志链 并不好排查 可以按照上面的提示调整下 backlog 或者配置 proxy_next_upstream 来缓解
|
27
dusu 2022-09-30 22:14:57 +08:00 via iPhone
1. Accesslog 里把 upstream_response_time 写上
2. 自己写个 bash 统计上游平均响应时长 3. ss -s 看看系统连接情况 4. ss -tlnp 看 backlog 占用情况 |
29
julyclyde 2022-10-08 11:45:38 +08:00
你把 upstream server address 记录下来看看,有些请求可能会有好几个 upstream server address
|