一次SocketTimeout问题排查
日志中长连接上的处理出现sockettimeout 异常
-
出现异常是偶发性的
排查思路
服务是否负载高
- 统计请求量,服务负载并不高
服务是否被hang住
- 每隔5秒 pstack <进程号> ,未发现异常代码堆栈进程号>
抓包
- tcpdump -i <网卡名> -w issue.pcap 包中有大量的retransmission 包,包被重传了网卡名>
包被重传的场景
- 网络拥塞
- 网络状况不良,丢包
- 等等
在排查一筹莫展的时候,客户仍出了一条关键信息:网络中的防火墙会将空闲超4分钟的连接断开,并且不会发送rst包,如图:
结论
server设置的keepalive最大时长是10分钟,防火墙上的空闲阈值先达到,连接被断开,client此时不会知道连接被断开 此时还持有着连接,并且发送数据
解决方案
- 将server keepalive时长改短,小于4分钟
- 修改系统tcp keepalive时长,默认2小时,改为小于4分钟(选择了修改客户端的此方案) 修改net.ipv4.tcp_keepalive,如下图
问题并未得到解决
排查keepalive是否生效
- sysctl -p
- 抓包,没有找到发送keepalive包,但是在数据连接发送了keepalive包
- 排查代码,
IOReactorConfig.soKeepAlive
未设置为true,keepalive可被系统设置,也能被进程设置。- 设置进程的keepalive后,问题最终解决