searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

浅测TCP重传

2023-10-12 03:23:05
26
0

前言

关于TCP连接的状态变迁,还有TCP有重传机制,这里仅对重传机制在系统上的具体表现进行测试,因为之前仅知道在系统上,涉及到重传的内核参数有如下四个,但个中的细节还是不得而知
名称
默认值 建议值
描述
tcp_syn_retries 5 2 对于一个新建连接,内核要发送多少个 SYN连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右时间。。(对于大负载而物理通信良好的网络而言,这个值偏高,可修改为2.这个值仅仅是针对对外的连接,对进来的连接,是由tcp_retries1决定的)
tcp_retries1 3 3 放弃回应一个TCP连接请求前﹐需要进行多少次重试。RFC 规定最低的数值是3
tcp_synack_retries 5 2 对于远端的连接请求SYN,内核会发送SYN +ACK数据报,以确认收到上一个 SYN连接请求包。这是所谓的三次握手( threeway handshake)机制的第二个步骤。这里决定内核在放弃连接之前所送出的 SYN+ACK 数目。不应该大于255,默认值是5,对应于180秒左右时间。
tcp_retries2 15 5 在丢弃激活(已建立通讯状况)的TCP连接之前﹐需要进行多少次重试。默认值为15,根据RTO的值来决定,相当于13-30分钟(RFC1122规定,必须大于100秒).
这次测试主要是针对参数tcp_retries2,查询资料得知重传间隔RTO(Retransmission Timeout)一般是动态计算出来的(公式在不同的RFC中有所不同),且会采取指数回退(binary exponential backoff)的方式进行递增,也就是说假如第一次等待的时间是1s,那么后续依次是等待2s、4s、8s
那在linux上的体现是如何的呢,第一次等待超时时间是多少,默认重传总体耗时又是多久
 

测试环境

 
主机A:10.18.5.132 redis-cli
主机B:10.17.1.54 redis-server

测试流程

Step1

主机A使用redis-cli连接上主机B的redis-server,通过3次握手后建立起TCP连接
 
[root@master tcpTest]# netstat -atnlp|grep 10.17.1.54
tcp 0 0 10.18.5.133:40758 10.17.1.54:9011 ESTABLISHED 11004/./redis-cli
 
 
[root@localhost tcpTest]# netstat -antlp|grep 10.18.5.133
tcp 0 0 10.17.1.54:9011 10.18.5.133:40758 ESTABLISHED 12382/redis-serverli

 

Step2

主机A通过redis-cli发送PING请求,TCP连接状态正常
 

Step3

开启FW,禁止主机A发数据到主机B,两端TCP连接依然是ESTABLISHED状态(同Step1记录的结果)

Step4

再次从主机A发送PING请求,记录被FW丢弃的数据包
 
根据上面的抓包结果,可以分析出每次重传的等待时间了,第一次的等待时间大概为200ms,最大的等待时间为120s,指数增长到了120就封顶了,看来应该是系统作了限制
发包 等待次数
RTO(s)
发PING    
  等待1 0.200365
重传1    
  等待2 0.402045
重传2    
  等待3 0.803957
重传3    
  等待4 1.607988
重传4    
  等待5 3.216799
重传5    
  等待6 6.431175
重传6    
  等待7 12.86406
重传7    
  等待8 25.72797
重传8    
  等待9 51.45601
重传9    
  等待10 102.9129
重传10    
  等待11 120
重传11    
  等待12 120
重传12    
  等待13 120
重传13    
  等待14 120
重传14    
  等待15 120
重传15    
  等待16 120
返回超时    
 
程序在重传第15次之后还等待了120秒才超时报错退出,丢弃TCP连接
 

Step5

查看两端机器的TCP连接状态,主机A上的TCP连接经过15次重传失败超时后被丢弃了,而主机B上的连接依然存在,看来主机A在丢弃连接的时候也并没有正常发送FIN包到对端
多次测试积累了一堆半打开的TCP连接
 

查看linux内核源码

 
#define TCP_RTO_MAX ((unsigned)(120*HZ))
#define TCP_RTO_MIN ((unsigned)(HZ/5))
 
 
------------------------------------------
 
static inline void tcp_bound_rto(const struct sock *sk)
{
if (inet_csk(sk)->icsk_rto > TCP_RTO_MAX)
inet_csk(sk)->icsk_rto = TCP_RTO_MAX;
}
 
从源码中可以看到TCP_RTO是有最小值与最大值的,当实际计算出来的rto大于最大值的时候会以最大值为准,而HZ可以理解为1s,所以120*HZ就是120秒,HZ/5就是200ms
 
HZ表示CPU一秒种发出多少次时间中断--IRQ-0,Linux中通常用HZ来做时间片的计算

 

0条评论
作者已关闭评论
尹****进
2文章数
0粉丝数
尹****进
2 文章 | 0 粉丝
尹****进
2文章数
0粉丝数
尹****进
2 文章 | 0 粉丝
原创

浅测TCP重传

2023-10-12 03:23:05
26
0

前言

关于TCP连接的状态变迁,还有TCP有重传机制,这里仅对重传机制在系统上的具体表现进行测试,因为之前仅知道在系统上,涉及到重传的内核参数有如下四个,但个中的细节还是不得而知
名称
默认值 建议值
描述
tcp_syn_retries 5 2 对于一个新建连接,内核要发送多少个 SYN连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右时间。。(对于大负载而物理通信良好的网络而言,这个值偏高,可修改为2.这个值仅仅是针对对外的连接,对进来的连接,是由tcp_retries1决定的)
tcp_retries1 3 3 放弃回应一个TCP连接请求前﹐需要进行多少次重试。RFC 规定最低的数值是3
tcp_synack_retries 5 2 对于远端的连接请求SYN,内核会发送SYN +ACK数据报,以确认收到上一个 SYN连接请求包。这是所谓的三次握手( threeway handshake)机制的第二个步骤。这里决定内核在放弃连接之前所送出的 SYN+ACK 数目。不应该大于255,默认值是5,对应于180秒左右时间。
tcp_retries2 15 5 在丢弃激活(已建立通讯状况)的TCP连接之前﹐需要进行多少次重试。默认值为15,根据RTO的值来决定,相当于13-30分钟(RFC1122规定,必须大于100秒).
这次测试主要是针对参数tcp_retries2,查询资料得知重传间隔RTO(Retransmission Timeout)一般是动态计算出来的(公式在不同的RFC中有所不同),且会采取指数回退(binary exponential backoff)的方式进行递增,也就是说假如第一次等待的时间是1s,那么后续依次是等待2s、4s、8s
那在linux上的体现是如何的呢,第一次等待超时时间是多少,默认重传总体耗时又是多久
 

测试环境

 
主机A:10.18.5.132 redis-cli
主机B:10.17.1.54 redis-server

测试流程

Step1

主机A使用redis-cli连接上主机B的redis-server,通过3次握手后建立起TCP连接
 
[root@master tcpTest]# netstat -atnlp|grep 10.17.1.54
tcp 0 0 10.18.5.133:40758 10.17.1.54:9011 ESTABLISHED 11004/./redis-cli
 
 
[root@localhost tcpTest]# netstat -antlp|grep 10.18.5.133
tcp 0 0 10.17.1.54:9011 10.18.5.133:40758 ESTABLISHED 12382/redis-serverli

 

Step2

主机A通过redis-cli发送PING请求,TCP连接状态正常
 

Step3

开启FW,禁止主机A发数据到主机B,两端TCP连接依然是ESTABLISHED状态(同Step1记录的结果)

Step4

再次从主机A发送PING请求,记录被FW丢弃的数据包
 
根据上面的抓包结果,可以分析出每次重传的等待时间了,第一次的等待时间大概为200ms,最大的等待时间为120s,指数增长到了120就封顶了,看来应该是系统作了限制
发包 等待次数
RTO(s)
发PING    
  等待1 0.200365
重传1    
  等待2 0.402045
重传2    
  等待3 0.803957
重传3    
  等待4 1.607988
重传4    
  等待5 3.216799
重传5    
  等待6 6.431175
重传6    
  等待7 12.86406
重传7    
  等待8 25.72797
重传8    
  等待9 51.45601
重传9    
  等待10 102.9129
重传10    
  等待11 120
重传11    
  等待12 120
重传12    
  等待13 120
重传13    
  等待14 120
重传14    
  等待15 120
重传15    
  等待16 120
返回超时    
 
程序在重传第15次之后还等待了120秒才超时报错退出,丢弃TCP连接
 

Step5

查看两端机器的TCP连接状态,主机A上的TCP连接经过15次重传失败超时后被丢弃了,而主机B上的连接依然存在,看来主机A在丢弃连接的时候也并没有正常发送FIN包到对端
多次测试积累了一堆半打开的TCP连接
 

查看linux内核源码

 
#define TCP_RTO_MAX ((unsigned)(120*HZ))
#define TCP_RTO_MIN ((unsigned)(HZ/5))
 
 
------------------------------------------
 
static inline void tcp_bound_rto(const struct sock *sk)
{
if (inet_csk(sk)->icsk_rto > TCP_RTO_MAX)
inet_csk(sk)->icsk_rto = TCP_RTO_MAX;
}
 
从源码中可以看到TCP_RTO是有最小值与最大值的,当实际计算出来的rto大于最大值的时候会以最大值为准,而HZ可以理解为1s,所以120*HZ就是120秒,HZ/5就是200ms
 
HZ表示CPU一秒种发出多少次时间中断--IRQ-0,Linux中通常用HZ来做时间片的计算

 

文章来自个人专栏
文章 | 订阅
0条评论
作者已关闭评论
作者已关闭评论
0
0