近期遇到一个奇怪的问题,客户端到服务器的连接偶发超时,通过抓包,看到服务端收到了客户端的SYN包,但就是不回复SYN ACK,通过网上查找资料,详细原因如下:
服务器同时设置tcp_timestamps=1和tcp_tw_recycle=1,就会缓存每个客户端TCP通信数据包中最新的时间戳,后续请求中如果时间戳小于缓存的时间戳,即视为无效,相应的数据包会被直接丢弃。
启用该功能后,60s内同一源ip主机的socket connect请求中的timestamp必须是递增的。当多个客户端通过NAT方式联网(所有客户端使用用一个广域网IP访问,例如家庭局域网,事实上国内普通用户上网基本上都是NAT方式)并与服务端交互时,服务端看到的是同一个IP,也就是服务端看到的只是同一个客户端,由于这些客户端的时间可能存在差异,于是乎从服务端的视角看,便可能出现时间戳错乱的现象,进而直接导致时间戳小的数据包被丢弃。具体的表现通常是有些客户端连接成功,有些失败。
tcp_timestamps与tcp_tw_recycle必须同时配置才会生效,在/etc/sysctl.conf配置文件中中配置,如果配置文件中没有,可以通过查看这两个文件内容查看当前配置:
cat /proc/sys/net/ipv4/tcp_timestamps(默认值是1)
cat /proc/sys/net/ipv4/tcp_tw_recycle(默认值是0)