上游超时后 Nginx 返回 502:先分清是哪一层超时
上游超时后 Nginx 返回 502:先分清是哪一层超时
一次线上故障里,Nginx 日志里全是 502,用户看到的是空白页。第一反应是后端挂了,实际后端进程还在,只是响应变慢了,Nginx 等不及就断开了。
Nginx 里和上游超时有关的三个参数,作用不一样:
proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 30s;
proxy_connect_timeout 是和上游建立连接的等待时间,连接不上就报 502。proxy_send_timeout 是把请求发给上游的等待时间。proxy_read_timeout 是发完请求、等上游回包的等待时间,这次故障就是这个值太小:上游一个报表接口平时 2 秒,大促时跑到 35 秒,Nginx 在 30 秒就断开了,日志里是 upstream timed out。
定位方法
先看 Nginx 错误日志里 upstream 的地址和耗时,再看上游应用日志里同一个请求的处理耗时。两个时间对上,才能确定是上游慢,而不是网络断开。
这次对下来:Nginx 日志 upstream response time 是 30 秒整,上游日志里这个请求处理了 35 秒,说明请求确实到了上游,只是回得慢。把 proxy_read_timeout 从 30 秒调到 60 秒,502 马上消失,但这只是让用户等更久,不是修好了慢接口。
真正的修法
报表接口慢,是因为它每次都全量算过去 90 天的数据。改成按天预聚合,接口耗时从 35 秒降到 1.2 秒,proxy_read_timeout 就可以保持 30 秒不动。超时参数是兜底,不是用来掩盖慢接口的。
还有一个容易漏的点:上游是多实例时,Nginx 默认会把超时的请求重试到下一个实例。如果接口不是幂等的,重试会造成重复写入。这次报表接口是只读查询,重试没问题;如果是写接口,要把 proxy_next_upstream 关掉,或者只在连接失败时重试:
proxy_next_upstream error timeout http_502;
proxy_next_upstream_timeout 10s;
proxy_next_upstream_tries 2;
检查清单
出 502 先分三步:看 Nginx 错误日志的 upstream 耗时,看上游应用日志的实际处理耗时,看上游实例是不是真的存活。三个时间对不上,就不要急着改超时参数。超时参数调大只能换用户等待时间,慢接口本身还是要修。
- 点赞
- 收藏
- 关注作者
评论(0)