`
jiagou
  • 浏览: 2533831 次
文章分类
社区版块
存档分类
最新评论

TCP通讯时对侧主机崩溃或网络异常的检出

 
阅读更多
一、问题描述:
在TCP通讯时,经常会出现对侧主机异常或网络故障的情况,这个时候需要能快速的检出故障,做出相应的处理措施。
下面描述为最近遇到的一个案例:
linux系统内核为2.6.18
设置的保活时间为:
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_time = 7200
超时重传关闭连接的最大次数:
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_orphan_retries = 0
程序中设置socke的保活机制时间
keepidle = 10
keepintvl = 5
keepcnt = 3
空闲时间超过10S开始发送探测报文段,每隔5秒发送一次如果一直无应答 连续发送三次即终止该连接。
在对侧主机崩溃或者网络断开的情况下,按照该理论计算,应该在10+5*2=25s内检测出错误并且断开连接。
在实际测试中如果在这个过程中应用层没有发送报文的话,检测时间与保活机制吻合。但是如果应用层有发送报文并且发送间隔为8S的时候,对侧网络断开后需要10多分钟的时间才能检出并中断连接。

二、分析:
在有报文下发的时候,保活机制并未生效。但是10多分钟的检出时间和系统的保活机制时间很吻合,但是由于系统的设置的空闲时间为2小时,所以不可能时系统的保活机制生效。
那应该是什么机制起的作用呢,分析两种情况的区别,一种应用层没有报文发送,此时应该为典型的保活机制应用场景,实现现象也说明保活机制正常运行;另一种应用层有报文发送,此时链路并非空闲状态,按照TCP/IP卷一种的介绍,此时应该保活机制并未生效,起作用的应该是重传超时机制。查看系统中的相关参数net.ipv4.tcp_retries2 = 15,按照TCP/IP中推荐的参数值和初始化值计算后的时间应该为(1+2+4+8+16+32+64+64*8)*1.5 = 639S = 15.975与测试时间基本吻合。更改net.ipv4.tcp_retries2 = 5后,测试时间为(1+2+4+8+16)*1.5 = 46.5s与测试时间也吻合。因此在有报文发送的时候,TCP层靠重传机制检出网络故障。

三、结果:
在没有报文传输的情况下,靠保活机制来检出网络故障;
如果应用层发送报文的间隔时间小于保活机制检出故障的时间,在本地网络正常,对侧网络断开或者对侧主机崩溃的情况下,由于本地的socket任然正常,发送报文并不会出错。此时检出错误使用的超时重传机制,通过重传的次数tcp_retries2来控制错误检出的时间,即达到重传次数还未收到确认后即认为网络是断开的,并关闭socket。也可以通过应用层增加超时机制的判断,并且在达到判断逻辑后由应用层关闭socket,达到检出错误的目的。

上述内容涉及到的知识和方法请参照下面几篇文章:

TCP重传机制
linux系统和window系统下关于tcp相关参数介绍

TCP定时器介绍

linux系统下TCP参数查看和设置 .

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics