一、介绍
当TCP连续大量的发送数据的时候,当出现丢包的时候可以有足够的dup ACK来触发快速重传。但是internet上还有大量的交互式服务,这类服务一般都是由小包组成,而且一次操作中需要传输的数据包一般比较少,比如在线游戏、股票交易等,这一类数据流我们就称呼为thin stream。在一次交互式操作触发一次TCP传输的时候,如果传输的这个数据包发生丢包,很可能后面没有足够的dup ACK来触发快速重传,最终只能依赖RTO超时来进行重传。还有一种受限传输的场景,如果发送窗口受到拥塞控制的限制只能发送出少量的TCP报文的时候,如果丢包也可能会因为收不到足够的dup ACK而不能触发快速重传。关于拥塞控制我们后续内容会介绍。这样会降低用户体验。同时如果RTO多次指数回退,可能会进一步进一步降低用户体验。之前我们介绍过RTO指数回退的目的是降低网络拥塞,而实际上交互式操作一般数据量很小,没有必要通过指数回退来降低网络拥塞。
综上介绍,为了改善thin stream的传输,linux针对引入了两个控制参数
/proc/sys/net/ipv4/tcp_thin_dupack:当该开关打开的时候,只需要一个dup ACK且缓存中没有待发送数据就可以触发快速重传
/proc/sys/net/ipv4/tcp_thin_linear_timeouts:当该参数打开的时候,前6次RTO超时触发的重传并不进行指数回退。
linux中会判断如果当前没有处于初始的慢启动过程(慢启动后续拥塞控制介绍)并且已经发出去的还没有收到ACK的数据包的个数小于4则会认定为thin stream。
二、wireshark示例
设置tcp_retries2=8,tcp_early_retrans=0,tcp_retrans_collapse=0,tcp_thin_dupack=1,tcp_thin_linear_timeouts=1,tcp_discard_on_port =9877;进行如下测试。
1、缓存中没有待发送数据,正常触发thin stream
- 其中No7-No8处的RTO超时重传时候,server端发出去的未收到ACK的包个数为1(No6包),当RTO超时的时候,TCP退出初始的慢启动过程,因此linux判定为thin stream,进而我们看到RTO超时时候没有触发指数回退(No6-No9之间每个数据包的发送间隔大约都是1.5s左右)。
- 接着重传成功后,连续发送两个数据包(No11和No12),此时server端发出的但尚未收到ACK确认包的数据包个数为2个。因为收到拥塞控制中慢启动的限制,此时server端最多只能发送这两个数据包。client模拟No11数据包传输丢失,响应No12数据包回复一个ACK确认包,注意这个确认包的ack number与No10确认包一样,同时包含一个SACK选项告诉server端已经收到了No12数据包
- server端认定这个数据包为dup ACK,同时数据流为thin stream,因此一个dup ACK就会触发快速重传,即No14数据包。对于No14数据包,wireshark显示为乱序包实际是一个快速重传包。另外对于No13报文,wireshark显示为No10的dup ACK,实际上linux的处理是因为No13携带有有效的SACK选项才被认定为dup ACK报文的,相关内容参考前面SACK重传的介绍。
- 快速重传没有收到ACK确认包的时候,接着触发RTO超时重传,可以看到前6次重传(No15-No20) 都没有触发指数会退,RTO一直是1.5s左右。直到第7次重传(No21)后,RTO开始进行指数回退。
2、缓存中有待发送数据不会触发thin stream重传
这个示例与之前类似,不同的是在第一次RTO超时重传成功后,server端应用层写入3个TCP报文,但是由于拥塞控制,server端TCP只能发出两个报文No11和No12。接着cilent模拟丢失No11报文,对No12乱序报文回复一个ACK确认包,同时包含一个SACK选项告诉server端已经收到了No12数据包。此时因为缓存中还有一个TCP报文待发送就不会触发thin stream的快速重传而是选则发送新数据来进一步触发dup ACK。
补充说明:
1、http://home.ifi.uio.no/paalh/students/AndreasPetlund-phd.pdf