背景
在线上环境中,客户反馈经常会出现Connection timed out问题,对报错的原因进行排查,并最终定位到问题并进行总结。
错误日志
2020/03/17 12:32:30 [error] 46678#46678: *7328557653 connect() failed (110: Connection timed out) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: , request: "POST /post/result/lol?type=Bet HTTP/1.1", upstream: "http://xxx.xxx.xxx.xxx:xxx/post/result/lol?type=Bet", host: "xxx.xxx.xxx.xxx:xxx"
2020/03/17 12:32:30 [error] 46675#46675: *7328557656 connect() failed (110: Connection timed out) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: , request: "POST /post/result/csgo?type=RollingBet HTTP/1.1", upstream: "http://xxx.xxx.xxx.xxx:xxx/post/result/csgo?type=RollingBet", host: "xxx.xxx.xxx.xxx:xxx"
排查思路
- 看到time out,以为是服务器或者nginx性能不足
- 使用ab压测工具,对相关Req进行压测,然后监控相关服务器性能和nginx性能。
- 看了下监控平台,相关服务器性能都比较平稳,没有较大的波动。
- 继续观察nginx的监控,nginx的active数量并没有超出设定的最大值。
结论:排除相关服务器性能问题
- 根据time out问题,查看了nginx相关源码,发现是getsockopt这个系统调用发生超时错误。可以知道高并发的时候,导致backend负载过高,不能及时处理nginx的req导致time out问题。
解决方法
检查了相关nginx的upstream的相关配置,发现keepalive设置的值较小,把值设定了1000的时候,继续ab压测多次观察,发现time out问题没有复现,之前每分钟复现一次time out,现在不会在复现。
反思
- keepalive是什么?
针对第一个问题,查看了相关nginx资料,对keepalive介绍
The connections parameter sets the maximum number of idle keepalive connections to upstream servers
请注意空闲keepalive连接的最大数量中空闲这个关键字,很多人会产生另外一个误解:认为这个参数是设置到upstream服务器的长连接的数量,分歧在于是最大连接数还是最小连接数当使用nginx作为反向代理时。但nginx文档空否定了这个说法。
t should be particularly noted that the keepalive directive does not limit the total number of connections to upstream servers that an nginx worker process can open.
- 如何设定keepalive的值?
nginx长连接消耗内存,设置少了,就会产生很多time-wait连接占用端口。所以这里设定值需要经过计算。根据QPS和平均响应时间大体能计算出需要的长连接的数量。比如10000 QPS和100毫秒响应时间就可以推算出需要的长连接数量大概是1000. 然后将keepalive设置为这个长连接数量的10%到50%。
- 其它注意问题
当使用nginx作为反向代理时,为了支持长连接,需要做到两点:
- 从client到nginx的连接是长连接
- 从nginx到server的连接是长连接
从HTTP协议的角度看,nginx在这个过程中,对于客户端它扮演着HTTP服务器端的角色。而对于真正的服务器端(在nginx的术语中称为upstream)nginx又扮演着HTTP客户端的角色。