数据库服务器Tcp_Timestamp和recycle引发的大量
0 - 现象
若同时开启timestamp和recycle参数,会由于引发per-host的PAWS机制,导致连接成功率降低。
产生问题:
- 什么是timestamp和recycle?
- 什么是PAWS机制?
- 为什么成功率会降低?
1 - 什么是timestamp和recycle?
tcp_timestamps的本质是记录数据包的发送时间。
基本步骤如下:
- 发送方在发送数据时,将一个timestamp(表示发送时间)放在包里面
- 接收方在收到数据包后,在对应的ACK包中将收到的timestamp返回给发送方(echo back)
- 发送发收到ACK包后,用当前时刻now - ACK包中的timestamp就能得到准确的RTT
RTT(Round Trip Time)由三部分组成:链路的传播时间(propagation delay)、末端系统的处理时间、路由器缓存中的排队和处理时间(queuing delay)
简单来说就是我发送一个数据包,然后对端回一个ack,那么当我接到ack之后,就能计算出从我发送出包到接到过了多久,这个时间就是RTT,所以RTT的变化在一定程度上反应了网络的拥塞程度。
RTO就是tcp在发送一个数据包之后,会启动一个重传定时器,而RTO就是这个定时器的重传时间。 在通俗的讲就是,我一开始预先算个定时器时间,如果你回复了ack那正好,如果没有回复给我ack,然后RTO定时器的时间又到了,那么我就重传。
产生问题:
- 为什么需要timestamp?
- timestamp存在什么负面影响?
2 - 为什么需要timestamp?
若没有timestamp就会采用SKB->when的方式计算RTT,基本步骤如下:
- TCP层在发送出一个SKB时,使用skb->when记录发送出去的时间
- TCP层在收到SKB数据包的确认时,使用now - skb->when来计算RTT
这时会存在一个缺陷,如当进行如下操作:
- tcp层首次发送SKB时间是send_time1,然后丢包发生重传,重传一个数据包的时间是send_time2
- tcp层收到SKB的确认包的时间是recv_time
这样无法判断recv_time对应ACK是确认第一次数据包的发送还是确认第二次重传的数据包。
3 - timestamp存在什么负面影响?
会产生10字节的TCP header开销
4 - 什么是recycle?
表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。对客户端和服务器同时起作用,开启后在 3.5*RTO 内回收,RTO 200ms~ 120s 具体时间视网络状况。
5 - 什么是Per-host PAWS机制?
在高带宽下,TCP序列号可能在较短的时间内就被重复使用(recycle/wrapped),就可能导致同一条TCP流在短时间内出现序号一样的两个合法的数据包及其确认包!
PAWS机制就是为了应对这一现象设计的,这种机制要求所有来个同一个host IP的TCP数据包的
timestamp值是递增的。当收到一个timestamp值,小于服务端记录的对应值后,则会认为这是一个过期的数据包,然后会将其丢弃。
6 - 为什么成功率会降低?
- 同时开启tcp_timestamp和tcp_tw_recycle会启用TCP/IP协议栈的per-host的PAWS机制
- 经过同一NAT转换后的来自不同真实client的数据流,在服务端看来是于同一host打交道
- 虽然经过同一NAT转化,但由于不同真实client会携带各自的timestamp值,因而无法保证整过NAT转化后的数据包携带的timestamp值严格递增
- 当服务器的per-host PAWS机制被触发后,会丢弃timestamp值不符合递增条件的数据包