1、现象:
nginx服务器抓包,对端请求建联,建联timestamps=2619129744,3秒内无响应返回tcp retransmission(timestamps=2619132744)。上一笔建联timestamps=3051995119,最后fin ack的timestamps=3052689066。下一笔建联timestamps=3052689066,结束ack的timestamps=3052764098。
建联SYN返回tcp transmissin失败后,也没有返回ack包。
2、分析:
TCP有一种行为,可以缓存每个连接最新的时间戳,后续请求中如果时间戳小于缓存的时间戳,即视为无效,相应的数据包会被丢弃。意思就是同一个源IP来连接同一个目的端口的数据包时间戳必须是递增的。
Linux参数tcp_timestamps和tcp_tw_recycle控制上述行为,因为tcp_timestamps缺省就是开启的,所以当tcp_tw_recycle被开启后(在我们的init初始化服务器脚本中这个参数就置为1开启),这种行为就被激活了。
对于后端服务器来说,请求的源地址就是专线出口的地址,加上web端口会复用,所以从后端服务器的角度看,原本不同客户端的请求经过LVS的转发,就可能会被认为是同一个连接,加之不同客户端的时间可能不一致,所以就会出现时间戳错乱的现象,于是后面的数据包就被丢弃了,具体的表现通常是是客户端明明发送的SYN,但服务端就是不响应ACK。(tcp_timestamps和tcp_tw_recycle-优快云博客)
应该有多台设备发送request请求,不同机器赋值了不同的timestamps,但都由一个专线ip出口。
另,据网上资料,这两个参数在内核2.4以上版本就禁用了,很多负载均衡设备会清空timestamps值,但我们专线没有什么负载均衡。