本帖最后由 Hacking 于 2022-10-3 13:35 编辑
最近抓包看到了一个以前没有见过(或者没有留意)的提示“TCP Spurious Retransmission”,如下图:
查询了下官方的资料,TCP Spurious Retransmission这种情况下,发送端认为发送的package已经丢失了,所以重传了,尽管此时接收端已经发送了对这些包的确认。
导致TCP Spurious Retransmission这种虚假超时重传的原因有很多种:
(1)对于部分移动网络,当网络发生切换时会导致网络延时突增
(2)当网络的可用带宽突然变小时,网络rtt会出现突增的情况,这会导致虚假超时重传
(3)网络丢包(原始和重传的包都有可能丢包)会导致虚假重传超时。
当Client端收到Server的SYN+ACK应答后,其状态变为ESTABLISHED,并发送ACK包给Server;如果此时ACK在网络中丢失,那么Server端该TCP连接的状态为SYN_RECV,并且依次等待3秒、6秒、12秒后重新发送SYN+ACK包,以便Client重新发送ACK包,以便Client重新发送ACK包。Server重发SYN+ACK包的次数,可以通过设置/proc/sys/net/ipv4/tcp_synack_retries修改,默认值为5。如果重发指定次数后,仍然未收到ACK应答,那么一段时间后,Server自动关闭这个连接。但是Client认为这个连接已经建立,如果Client端向Server写数据,Server端将以RST包响应,方能感知到Server的错误。
总结一下:
Linux的超时重传默认是3秒,这就意味这,一旦发生丢包,用户的体验将会很不好,因此可以采用强制快速重传技术来进行提速(Spurious SYN/SYN-ACK retransmissions),将超时重传时间强制设定为1秒。但这可能会导致duplicate packets,可以通过修改TS(tcp_sack参数,链路质量良好的情况下一般设0)或DSACK(允许发多个ACK,这里也用设0的方式)等方式来进行改进。
- <div><div>sysctl -w net.ipv4.tcp_sack=0</div><div>sysctl -w net.ipv4.tcp_dsack=0</div><div>sysctl -p</div></div><div></div>
复制代码
|