开发反馈有个应用在后端数据库某次计划性重启后常常会出现数据库链接异常问题,经过监控系统的埋点数据,发现应用链接数据库异常有两类表现:
其一:链接超时
131148.00ms Tomcat Connection Pool
其二:链接耗时过长
DAL.getConnectionCost 64018mslinux
经过监控数据汇总,出现此异常问题来自应用群集中的多台WEB服务器,没有规律性,数据库服务器也没有作过系统版本升级及硬件调整,且数据库各主要性能指标正常,负载很低。所以最大可疑是网络通信上的异常致使,因而经过客户端/服务器端同时抓包进行分析。算法
分析后,发现数据包中有许多TCP Retransmission数据库
六次重连失败样例:
五次重连失败,第六次链接成功样例:
后端
TCP SYN重传次数与请求端的tcp_syn_retries参数值有关,本案例中应用WEB服务器设置为6(查看命令:sudo sysctl -a | grep tcp_syn_retries),即重试的间隔时间从1s开始每次都翻倍,6次的重试时间间隔为1s, 2s, 4s, 8s,16s,32S总共63s,第6次发出后还要等64s才知道第6次也超时了,因此总共须要 1s + 2s + 4s+ 8s+ 16s + 32s+64S =127S,TCP才会断开链接。服务器
所以上述问题描述中
“链接超时”计算公式为:1s + 2s + 4s+ 8s+ 16s + 32s+64S =127S
“建连耗时”计算公式与实际重试次数有关,以5次重试为例:1s + 2s + 4s+ 8s+ 16s + 32s=63S网络
查询资料得知TCP Retransmission问题很大可能与tcp_tw_recycle设置有关,在此参数开启后,服务端会对TCP包中timestamp有效性进行校验,数据包中的timestamp理应是顺序递增,如最新的数据包timestamp小于前一个包的timestamp,服务端则认为最新的数据包已过期从而丢弃,此问题常出如今NAT网络,如负载均衡设备后面,由于数据包通过转发,source_ip相同,可是后端不一样机器的timestamp不一样。负载均衡
检查数据库服务器配置,发现tcp_tw_recycle功能被开启,同时网卡统计中存在由于时间戳被拒的数据包信息
dom
netstat -s |grep reject
251286 passive connections rejected because of time stamp
795 packets rejects in established connections because of timestamp
关闭tcp_tw_recycle功能后,应用链接数据库恢复正常。本案例中为什么数据库服务器重启后应用报错,那是由于参数先前只是作了动态关闭,没有修改配置文件固化,重启后读到旧的配置从而致使应用忽然报错。tcp
本案例中的应用服务器与后端数据库直连,并不在NAT网络中,那理论上特定机器发送给DB的TCP包中timestamp数值是递增,不会出现乱序丢包问题,但实际抓包中的timestamp是乱序的,忽大忽小,没有规律性。post
在不一样Kernel版本环境中模拟用户请求,发如今不一样内核环境中,timestamp行为有明显差别
Kernel 4.10.13,TSecr(请求方timestamp)随机
Kernel 3.10,TSecr(请求方timestamp)递增
查询资料发现timestamp生成算法在linux kernel 4.10以后进行了调整,加入偏移因子,从而变为随机性。所以如开启了tcp_tw_recycle,即便在非NAT网络环境中也会出现丢包问题,tcp_tw_recycle的弊端更为突显,所以在4.12内核中被移除
tcp_tw_recycle在高版本内核中弊大于利,应保持系统默认设置,关闭参数。
https://mp.weixin.qq.com/s/uwykopNnkcRL5JXTVufyBw http://80x86.io/post/linux-kernel-v4.10.1-tcp-timestamps-random-offset-problem