背景:云服务器。
服务器现象:服务器出现不定时的连接卡顿,具体表现为业务访问报错,ssh连接失败,redis连接失败,数据库连接失败。过一分钟左右恢复正常。
排查:查看监控,cpu、内存、磁盘io都正常
一开始以为是带宽问题,服务器网络从5M调整到100M,也还是不行,使用MTR工具检测,结果正常。排除网络问题。
使用ping、tcping测试链路丢包情况,端口连接质量,均正常。
断断续续持续了很久,最后将问题范围缩小至服务器内核参数上。
在之前一段时间,由于设备连接服务器,tcp出现大量TIME_WAIT,为了解决TIME_WAIT,查询各种资料,在服务器启用了net.ipv4.tcp_tw_recycle参数。
将net.ipv4.tcp_tw_recycle值改为0,观察服务器,问题解决!
原因:
linux手册TCP协议官方原文:
tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
Enable fast recycling of TIME_WAIT sockets. Enabling this option is not recommended since this causes problems when working with NAT (Network Address Translation)
翻译过来为:启用TIME_WAIT套接字的快速回收。不建议启用此选项。在NAT网络中,会导致大量的TCP连接错误。
查阅了资料后,发现这个问题是同时由两个参数导致的,即:net.ipv4.tcp_tw_recycle和net.ipv4.tcp_timestamps。
而net.ipv4.tcp_timestamps是默认开启,所以当开启了net.ipv4.tcp_tw_recycle之后,kernal会校验客户端的数据包时间戳。因为各个客户端的时间不可能同步,无法保证他们的TCP请求的timestamp是严格递增的。所以当服务器收到的timestamp变小时,会认为这是一个过期的数据包,将其丢弃。