序言
只要系统之间有交互,那么就会有连接数,连接数的告警阈值一般设置个几万,当连接数开始告警之后,怎么来排查呢?
连接数过多,会消耗cpu,内存,文件句柄等资源,其实也还好,当解决不了的时候,你可以把连接数的阈值调高一点,或许10w才开始告警,或者30w才开始告警也行,只要cpu和内存不告警,其实也没那么紧急。
服务端连接数异常告警排查
1 查看连接状态
当nginx充当转发功能的时候,连接数告警应该很正常,特别是在qps很大的情况下,当收到告警之后,一般接下来的操作就是登录上服务,使用netstat或者ss的命令来进行查看。
netstat -tnp|awk '{print $6}'|sort -nr|uniq -c
ss -tap|awk '{print $6}'|sort -nr|uniq -c
注意:在使用ss命令的时候,如果写的命令和netstat一样,
在默认情况下,ss是不会显示time wait的连接状态的,
因为ss认为这种状态不重要
当命令执行之后,我们就知道占用连接最多的是哪个了,在正常情况下,你会发现TIME-WAIT连接占用的很多,那么接下来就是看下是哪些ip占用的多了。
#查看本地的ip中,哪些ip数量比较多
netstat -tnp|grep -i time|awk '{print $4}'|awk -F ":" '{print $1}'|sort -nr|uniq -c
#查看远端ip中,哪些ip数量比较多
netstat -tnp|grep -i time|awk '{print $5}'|awk -F ":" '{print $1}'|sort -nr|uniq -c
在当前的场景下,发现是与后端服务连接的time wait比较多,也就是上面的第二条命令显示的都是nginx的upstream的服务器,从而大致可以判断为,nginx与upstream的连接为短连接,未开启长连接配置
2 查看nginx的配置
在默认情况下,如果你在upsteam的配置中啥都没写,那么在默认情况下nginx与upstream的连接是属于短连接的。
Syntax: keepalive connections;
Default: —
Context: upstream
The connections parameter sets the maximum number of
idle keepalive connections to upstream servers
that are preserved in the cache of each
worker process. When this number is exceeded,
the least recently used connections are closed.
特别需要注意的keepalive的说明中,这个链接参数限制的是空闲的连接(不会限制后upstream的最大连接数),也就是最多保持的空闲连接数,而不是和数据库的一样,连接池总共有多大。
伴随着keepalive参数设置之后,还有其他的两个参数也可以设置:
Syntax: keepalive_timeout timeout;
Default:
keepalive_timeout 60s;
Context: upstream
Syntax: keepalive_requests number;
Default:
keepalive_requests 1000;
Context: upstream
在一般的情况下,这两个参数保持默认值就好了,如果并发很大的时候,那么可以将keepalive设置为300,将timeout和requests设置的大一点,这样可以减少连接被释放的次数。
如果keepalive_timeout设置的很小,那么就会导致连接不停地被释放,被创建,最直接的影响就是会增大请求的rt,消耗nginx的资源,有更高的连接和关闭的开销,并且会影响后端服务器的性能。
在upstream的长连接需要进行关闭时候,会按照四次挥手进行关闭连接,而且会等连接处理完成之后,再进行关闭,不像有些框架很暴力,到了时间之后,直接关闭,不管请求是否结束。
3 客户端的长连接
对于nginx来说,默认情况下就开启了客户端的长连接功能,所以一般只要配置超时时间即可。
Syntax: keepalive_timeout timeout [header_timeout];
Default:
keepalive_timeout 75s;
Context: http, server, location
需要注意的是,如果客户端的连接都是短连接,而没有长连接,那么就要查看客户端的请求头了,查看客户端的connection头部是否为close,强制要求使用短连接。
查看客户端使用的协议,是否是http1.0(默认都是短连接)。
如果未出现上述的情况,那就要检查nginx的配置中,是否将connection头部设置为"",否则不但客户端是短连接,还会影响nginx和upstream之间也是短连接。
如果客户端发送的connection头部是close,但是nginx设置了connection头部为"",那么其实nginx和后端依旧是长连接。
如果发现客户端的连接好多time wait怎么办?优化操作系统的内核参数(/etc/sysctl.conf):
net.ipv4.tcp_keepalive_time = 1200 使用tcp探测尽快处理空闲的连接
net.ipv4.tcp_fin_timeout = 30 设置fin wait2等待时间,减少等待关闭连接的时间,尽快释放系统资源
net.ipv4.tcp_max_tw_buckets 200000 控制timewait数量
net.ipv4.tcp_tw_recycle =0 禁用timewait的快速回收,已废弃,防止潜在网络问题
net.ipv4.tcp_tw_reuse = 1 启用timewait状态的连接便于新的连接
net.ipv4.tcp_timestamps = 1 启用tcp时间戳选项,提高网络传输效率,提高tcp连接安全性
net.ipv4.netdev_max_backlog = 262148 允许入队列的数据包的最大数量
nginx的复杂之处在于又是客户端,又是服务端,在充当客户端的时候,需要设置连接超时参数,在充当服务端的时候,也要设置连接超时参数,并且参数的名字还差不多,只不过是写的位置不一样,有的是在http段中,有的是在upstream段中。
抓包很有意思,但是你要在特定的时间内抓到特定的包,如果qps很大,一不小心磁盘就炸了,还没抓到对应的包。如果是偶发的现象,你去抓包,那就更加痛苦了,慢慢抓吧。
风言风语
不出现问题的时候,其实没必要优化,因为优化之后,你也不知道效果,只有出了问题,才知道优化的方向对不对。
看别人的配置弄个长连接,你也弄个长连接,至于能带来什么效果,不清楚不知道,说基础配置的看起来很简单,但是能解决什么问题,好像。。。很少看到。
有的问题,听别人讲的时候很清楚,但是仔细一思索,然后在用chatgpt查一查,更加迷茫了,再抓个包。。。emmm,疯了,无法解释的问题,除非去看源码了。
想少一点,人生会简单很多。。。