最新消息:

记一次TCP连接异常故障解决

sysctl admin 4461浏览 0评论
一.情况表现为
    1.在公司内网对站点的http访问:
        linux主机出现故障:curl以及抓包分析,发现服务端不响应linux客户端的请求,无法建立TCP连接,浏览器返回“无法连接到服务器”
        windows主机正常
    2.http访问质量下降:
        基调显示,新架构上线后,访问质量下滑,主要表现为
        2.1.访问提示“无法连接到服务器”
        2.2.仅少数人遇到这种故障,并且一天中不是每次访问都会遇到,而是出现时好时坏的现象
二.处理过程
    直接上google搜索关键字“服务器无法建立TCP连接”。
    翻了几页后,发现这篇博文:“http://www.sunchis.com/html/os/linux/2012/0518/413.html”。
    看了一下,和我们公司内网的表现一模一样,但各种问题(1为这方面基础知识薄弱,2为没有时间验证此配置)
    然后这种问题持续了n久…一直以为是内部设备问题
    后期搞不定了,大胆在线上启用这个参数“net.ipv4.tcp_timestamps = 0”,做了下测试后,发现故障解除,原故障机每次访问都正常了!
    不过还是不明其中原理,只是大意了解,同样处于NAT上网方式的用户里(与别人共用出口IP地址),如果你的时间戳小于别人的,那么服务器不会响应你的TCP请求,要忽略此项,将net.ipv4.tcp_timestamps = 0(/etc/sysctl.conf)
三.总结
    后期学习时,看见了一个更加详细的博客,讲的很详细,也引入了新的问题:http://huoding.com/2012/01/19/142
    ====== 小抄 ======
    其实,linux服务器原本对时间戳(timestamps)默认是不开启的,Linux是否启用这种行为取决于tcp_timestamps和tcp_tw_recycle,因为tcp_timestamps缺省就是开启的,所以当tcp_tw_recycle被开启后,实际上这种行为就被激活了。
    net.ipv4.tcp_tw_recycle又是啥呢,搜索了一下基本上是TIME_WAIT连接的回收参数
    当 net.ipv4.tcp_timestamps 没有设置(缺省为开启),并且 net.ipv4.tcp_tw_recycle 也开启时,这个坑爹的错误就出现了,但是注意,只表现在NAT网络环境中。而且,大多数博客,以及一些大牛们,都有说过要开启 net.ipv4.tcp_tw_recycle …
    ====== 小抄 ======
四.未完成的事项
    上文 http://huoding.com/2012/01/19/142 中提到的:
    1.(未验证)关闭timestamps后,tw_recycle功能是失效的问题
    2.(未验证)新的解决TIME_WAIT连接过多的方法:net.ipv4.tcp_max_tw_buckets = 10000 设置一个最大值,不过坏处是系统日志会提示:TCP: time wait bucket table overflow
===============================================================

针对有些用户能ping通我们的网站,但是连接时超时服务器没有任何响应,怀疑问题处在了了http的三次握手环节,这是决定通过抓包进行分析:

1、有问题机器的截图:

2、正常机器的截图:

3、发现问题

从抓包数据发现,web服务器对出问题机器和正常机器系统的tcp syn包都返回ACK包,但存在问题发出的tcp syn包有时候响应,有时候不响应。不响应时,终端与web服务器之间的tcp连接无法正常建立,导致页面不能打开。对比这两种数据包,就在时间戳上有差异,存在问题的机器发出的tcp syn包带有时间戳,因此怀疑时间戳问题导致的故障。

4、解决问题

既然怀疑是时间戳导致的,那我们就着手分析如果将出现问题的机器的时间戳去掉会不会解决问题。针对带有时间戳的tcp syn包不响应的问题,查阅了相关资料得知产生问题的原因是出问题系统中的注册表中有Tcp1323opts这个选项,会导致其在发包时加入时间戳,经过nat之后,如果前面相同的端口被使用过,且时间戳大于这个链接发出的syn中的时间戳,服务器上就会忽略掉这个syn,不返会syn-ack消息,表现为用户无法正常完成tcp3次握手,从而不能打开web页面。在业务闲时,如果用户nat的端口没有被使用过时,就可以正常打开;业务忙时,nat端口重复使用的频率高,很难分到没有被使用的端口,从而产生这种问题。

目前看有两种方法解决:

(1)    是在服务器上修改变量

首先我们先查看一下我们服务器net.ipv4.tcp_timestamps的默认值,如果该值为0测说名不是该问题导致,如果是1我们需要将该值设置为1。

查看默认值的方法:[root@localhost ~]# cat /proc/sys/net/ipv4/tcp_timestamps

修改该值的方法:vim /etc/sysctl.conf  添加 net.ipv4.tcp_timestamps=0

(2)修改客户端的注册表Tcp1323Opts设置为0。

 

备注:

Tcp1323Opts

说明:该参数控制 RFC 1323 时间戳与窗口缩放选项。默认情况下,启用时间戳与

窗口缩放,但是可以使用标志位进行控制。0 位控制窗口缩放,1 位控制时间戳。

值为0(禁用 RFC 1323 选项)

值为1(仅启用窗口缩放)

值为2(仅启用时间戳)

值为3(两个选项均启用)

 

net.ipv4.tcp_timestamps=0

说明:时间戳可以避免序列号的卷绕。一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。

值为0(禁用时间戳)

值为1(启用时间戳)

 

只有客户端和服务端都开启时间戳的情况下,才会出现能ping通不能建立tcp三次握手的情况,所以做为提供服务的公司,不可能保证所有的用户都关闭时间戳,这个功能,所以我们必须关闭时间戳,这样才能给所用用户提供正常的服务。

 

转载请注明:爱开源 » 记一次TCP连接异常故障解决

您必须 登录 才能发表评论!