tcp_tw_recycle和tcp_timestamps导致connect失败问题

http://blog.jobbole.com/70907/  一站式学习wireshark

近来线上陆续出现了一些connect失败的问题,经过分析试验,最终确认和proc参数tcp_tw_recycle/tcp_timestamps相关;

1. 现象
       第一个现象:模块A通过NAT网关访问服务S成功,而模块B通过NAT网关访问服务S经常性出现connect失败,抓包发现:服务S端已经收到了syn包,但没有回复synack;另外,模块A关闭了tcp timestamp,而模块B开启了tcp timestamp;
       第二个现象:不同主机上 的模块C(开启timestamp),通过NAT网关(1个出口ip)访问同一服务S,主机C1 connect成功,而主机C2 connect失败;

2. 分析
       根据现象上述问题明显和tcp timestmap有关;查看linux 2.6.32内核源码,发现tcp_tw_recycle/tcp_timestamps都开启的条件下,60s内同一源ip主机的socket connect请求中的timestamp必须是递增的。
        源码函数 :tcp_v4_conn_request(),该函数是tcp层三次握手syn包的处理函数(服务端);
        源码片段
             if ( tmp_opt.saw_tstamp  &&
                     tcp_death_row. sysctl_tw_recycle  &&
                     (dst = inet_csk_route_req(sk, req)) != NULL &&
                     (peer = rt_get_peer((struct rtable *)dst)) != NULL &&
                     peer->v4daddr == saddr) {
                     if ( get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL  &&
                            (s32)( peer->tcp_ts - req->ts_recent) >
                            TCP_PAWS_WINDOW ) {
                            NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
                            goto drop_and_release;
                     }
              }
        tmp_opt.saw_tstamp:该socket支持tcp_timestamp
        sysctl_tw_recycle:本机系统开启tcp_tw_recycle选项
        TCP_PAWS_MSL:60s,该条件判断表示该源ip的上次tcp通讯发生在60s内
        TCP_PAWS_WINDOW:1,该条件判断表示该源ip的上次tcp通讯的timestamp 大于 本次tcp


        分析: 主机client1和client2通过NAT网关(1个ip地址)访问serverN,由于timestamp时间为系统启动到当前的时间,因此,client1和client2的timestamp不相同;根据上述syn包处理源码,在tcp_tw_recycle和tcp_timestamps同时开启的条件下,timestamp大的主机访问serverN成功,而timestmap小的主机访问失败;

        参数: /proc/sys/net/ipv4/tcp_timestamps - 控制timestamp选项开启/关闭
                   /proc/sys/net/ipv4/tcp_tw_recycle - 减少timewait socket释放的超时时间

3. 解决方法
       echo 0 > /proc/sys/net/ipv4/tcp_tw_recycle;
       tcp_tw_recycle默认是关闭的,有不少服务器,为了提高性能,开启了该选项;
       为了解决上述问题,个人建议关闭tcp_tw_recycle选项,而不是timestamp;因为 在tcp timestamp关闭的条件下,开启tcp_tw_recycle是不起作用的;而tcp timestamp可以独立开启并起作用。
       源码函数 :   tcp_time_wait()
       源码片段:
            if ( tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp )
                   recycle_ok = icsk->icsk_af_ops->remember_stamp(sk);
               ......
            
              if (timeo < rto)
                      timeo = rto ;

              if (recycle_ok) {
                     tw->tw_timeout = rto;
              } else {
                     tw->tw_timeout = TCP_TIMEWAIT_LEN;
                     if (state == TCP_TIME_WAIT)
                             timeo = TCP_TIMEWAIT_LEN;
              }

              inet_twsk_schedule(tw, &tcp_death_row,  timeo,
                                 TCP_TIMEWAIT_LEN);

      timestamp和tw_recycle同时开启的条件下,timewait状态socket释放的超时时间和rto相关;否则,超时时间为 TCP_TIMEWAIT_LEN,即60s;

        内核说明文档 对该参数的介绍如下
       tcp_tw_recycle - BOOLEAN
       Enable fast recycling TIME-WAIT sockets. Default value is 0.
      It should not be changed without advice/request of technical
    experts.

原文链接:http://blog.sina.com.cn/u/2015038597


这个微博观点错的,你对内核参数的修改,必须是在理解透测的基础上。最佳优化,就是tcp_tw_recycle=1,tcp_timestamps=0。一方面降低TIME_WAIT,又不回出现nat连接不上的问题

您有没有看到怎么进入这段?

 else if (!isn) {

前面是有个判断,
    __u32 isn = TCP_SKB_CB(skb)->when;

我理解那个isn应该是非负的,所以这段代码应该进不来。

请赐教。谢谢!

先在我的水平还无法判断谁是谁非,留待以后吧,只是我知道recycle只是加快回收但是无法保证2MSL的效果,而time_stamp只是保证老的重复分解不会被误收。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值