为了能彻底讲清楚TIME_WAIT的原理及解决办法,本系列一共有4篇

彻底理解并解决服务器出现大量TIME_WAIT - 第一篇_YZF_Kevin的博客-CSDN博客

彻底理解并解决服务器出现大量TIME_WAIT - 第二篇_YZF_Kevin的博客-CSDN博客

彻底理解并解决服务器出现大量TIME_WAIT - 第三篇_YZF_Kevin的博客-CSDN博客

彻底理解并解决服务器出现大量TIME_WAIT - 第四篇_YZF_Kevin的博客-CSDN博客

第一篇博客中我们讲了 TIME_WAIT 出现的原理,引发的问题,解决办法等,如下

解决办法

1. 代码层修改,把短连接改为长连接,但代价较大
2. 修改 ip_local_port_range,增大可用端口范围,比如1024 ~ 65535
3. 客户端程序中设置socket的 SO_LINGER 选项
4. 打开 tcp_tw_recycle 和tcp_timestamps 选项,有一定风险,且linux4.12之后被废弃
5. 打开 tcp_tw_reuse 和 tcp_timestamps 选项
6. 设置 tcp_max_tw_buckets 为一个较小的值

下面我们接着对各个办法进行详细讲解

办法4. 打开 tcp_tw_recycle 和tcp_timestamps 选项,有一定风险,且linux4.12之后被废弃

官方文档中解释如下:
tcp_tw_recycle 选项作用为:Enable fast recycling TIME-WAIT sockets. Default value is 0.
tcp_timestamps 选项作用为:Enable timestamps as defined in RFC1323. Default value is 1

这两个选项是linux内核提供的控制选项,和具体的应用程序没有关系,而且网上也能够查询到大量的相关资料,但信息都不够完整,最主要的几个问题如下;
1)快速回收到底有多快?
2)有的资料说只要打开tcp_tw_recycle即可,有的又说要tcp_timestamps同时打开,到底是哪个正确?
3)为什么从虚拟机NAT出去发起客户端连接时选项无效,非虚拟机连接就有效?为了搞清楚上面的疑问,只能看代码,看出一些相关的代码供大家参考:
=====linux-2.6.37 net/ipv4/tcp_minisocks.c 269======

void tcp_time_wait(struct sock *sk, int state, int timeo)
{struct inet_timewait_sock *tw = NULL;const struct inet_connection_sock *icsk = inet_csk(sk);const struct tcp_sock *tp = tcp_sk(sk);int recycle_ok = 0;// 判断是否快速回收,这里可以看出tcp_tw_recycle和tcp_timestamps两个选项都打开的时候才进行快速回收,//且还有进一步的判断条件,后面会分析,这个进一步的判断条件和第三个问题有关if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp)recycle_ok = icsk->icsk_af_ops->remember_stamp(sk);if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets)tw = inet_twsk_alloc(sk, state);if (tw != NULL) {struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);//计算快速回收的时间,等于 RTO * 3.5,回答第一个问题的关键是RTO(RetransmissionTimeout)大概是多少const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);//。。。。。。此处省略很多代码。。。。。。if (recycle_ok) {//设置快速回收的时间tw->tw_timeout = rto;} else {tw->tw_timeout = TCP_TIMEWAIT_LEN;if (state == TCP_TIME_WAIT)timeo = TCP_TIMEWAIT_LEN;}//。。。。。。此处省略很多代码。。。。。。
}

这里讲下RTO(Retransmission Time Out):重传超时时间,即从数据发送时刻算起,超过这个时间便执行重传
RFC中有关于RTO计算的详细规定,一共有三个:RFC-793、RFC-2988、RFC-6298,Linux的实现是参考RFC-2988。
对于这些算法的规定和Linux的实现,有兴趣的同学可以自己深入研究,实际应用中我们只要记住Linux如下两个边界值:
=====linux-2.6.37 net/ipv4/tcp.c 126================
#define TCP_RTO_MAX ((unsigned)(120*HZ))
#define TCP_RTO_MIN ((unsigned)(HZ/5))
==========================================
这里的HZ是1s,因此可以得出RTO最大是120s,最小是200ms,对于局域网的机器来说,正常情况下RTO基本上就是200ms,因此3.5 RTO就是700ms
也就是说,快速回收是TIME_WAIT的状态持续700ms,而不是正常的2MSL
实测结果也验证了这个推论,不停的查看TIME_WAIT状态的连接,偶尔能看到1个

最后一个问题是为什么从虚拟机发起的连接即使设置了tcp_tw_recycle和tcp_timestamps,也不会快速回收,继续看代码:
tcp_time_wait函数中的代码行:recycle_ok = icsk->icsk_af_ops->remember_stamp(sk);对应的实现如下:
=====linux-2.6.37 net/ipv4/tcp_ipv4.c 1772=====

int tcp_v4_remember_stamp(struct sock *sk)
{//。。。。。。此处省略很多代码。。。。。。//当获取对端信息时,进行快速回收,否则不进行快速回收if (peer) {if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 ||((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&peer->tcp_ts_stamp <= (u32)tp->rx_opt.ts_recent_stamp)) {peer->tcp_ts_stamp = (u32)tp->rx_opt.ts_recent_stamp;peer->tcp_ts = tp->rx_opt.ts_recent;}if (release_it)inet_putpeer(peer);return 1;}return 0;
}

上面这段代码应该就是测试的时候虚拟机环境不会释放的原因,当使用虚拟机NAT出去的时候,服务器无法获取隐藏在NAT后的机器信息。
生产环境也出现了设置了选项,但TIME_WAIT连接数达到4W多的现象,可能和虚拟机有关,也可能和组网有关。
总结一下:
1)快速回收到底有多快?
答:局域网环境下,700ms就回收
2)有的资料说只要打开tcp_tw_recycle即可,有的又说要tcp_timestamps同时打开,到底是哪个正确?
答:需要同时打开,但默认情况下tcp_timestamps就是打开的,所以会有人说只要打开tcp_tw_recycle即可
3)为什么从虚拟机发起客户端连接时选项无效,非虚拟机连接就有效?
答:和网络组网有关系,无法获取对端信息时就不进行快速回收。

注意1

NAT(Network Address Translation即网络地址转换)环境下,打开 tcp_tw_recycle选项可能会引发其他问题,tcp_tw_recycle是依赖tcp_timestamps参数的。例如办公室的外网地址只有一个,所有人访问后台都会通过路由器做SNAT将内网地址映射为公网IP,由于服务端和客户端都启用了tcp_timestamps,因此TCP头部中增加时间戳信息,而在服务器看来,同一客户端的时间戳必然是线性增长的,但是,由于我的客户端网络环境是NAT,因此每台主机的时间戳都是有差异的,在启用tcp_tw_recycle后,一旦有客户端断开连接,服务器可能就会丢弃那些时间戳较小的客户端的SYN包,这也就导致了网站访问极不稳定。

简单来说就是,Linux会丢弃所有来自远端的timestramp时间戳小于上次记录的时间戳(由同一个远端发送的)的任何数据包。也就是说要使用该选项,则必须保证数据包的时间戳是单调递增的。同时从4.10内核开始,官方修改了时间戳的生成机制,所以导致 tcp_tw_recycle 和新时间戳机制工作在一起不那么友好,同时 tcp_tw_recycle 帮助也不那么的大。

此处的时间戳并不是我们通常意义上面的绝对时间,而是一个相对时间。很多情况下,我们是没法保证时间戳单调递增的,比如业务服务器之前部署了NAT,LVS等情况。相信很多小伙伴上班的公司大概率实用实用各种公有云,而各种公有云的 LVS 网关都是 FullNAT 。所以可能导致在高并发的情况下,莫名其妙的 TCP 建联不是那么顺畅或者丢连接

主机A SIP:P1 (时间戳T0) —> Server

主机A断开后
主机B SIP:P1 (时间戳T1) T1 < T0 —> Server 丢弃

具体见:记一次由tcp_tw_recycle参数引发的血案_鲁班6号的技术博客_51CTO博客

注意2

在linux内核版本从4.12之后,tcp_tw_recycle已经被废弃了,详见

Troubleshooting sysctl: cannot stat /proc/sys/net/ipv4/tcp_tw_recycle: No such file or directory

我的linux机器是ubuntu,查看内核版本如下

linux 内核版本已经4.15了,如果开发tcp_tw_recycle,执行命令刷新的话,就会有如下报错

提示得很明确,这个文件不存在

sysctl: cannot stat /proc/sys/net/ipv4/tcp_tw_recycle: No such file or directory

综上

可以看出这种方法不是很保险,在实际应用中可能受到虚拟机、网络组网、防火墙之类的影响从而导致不能进行快速回收。

彻底理解并解决服务器出现大量TIME_WAIT - 第三篇相关推荐

  1. 彻底理解并解决服务器出现大量TIME_WAIT - 第四篇

    为了能彻底讲清楚TIME_WAIT的原理及解决办法,本系列一共有4篇 彻底理解并解决服务器出现大量TIME_WAIT - 第一篇_YZF_Kevin的博客-CSDN博客 彻底理解并解决服务器出现大量T ...

  2. 彻底理解并解决服务器出现大量TIME_WAIT - 第一篇

    为了能彻底讲清楚TIME_WAIT的原理及解决办法,本系列一共有4篇 彻底理解并解决服务器出现大量TIME_WAIT - 第一篇_YZF_Kevin的博客-CSDN博客 彻底理解并解决服务器出现大量T ...

  3. 跟我学,你的服务器安全吗?第三篇----apache安全篇

    目录 前言 1. 确保默认情况下拒绝访问OS根目录(高危) 2. 确保对OS根目录禁用覆盖(高危) 3. 配置专门用户账号和组用于运行 Apache(高危) 4. 确保已锁定apache用户帐户(高危 ...

  4. 深入理解Tomcat和Jetty源码之第三篇tomcat系统架构上:连接器是如何设计的

    我们都知道Tomcat服务器是包括连接器和容器,​那他们内部具体是怎么实现的呢?今天让我们一起来学习一下~ 1.tomcat基础知识 2.tomcat和service的关系 3.tomcat的详细介绍 ...

  5. 理解和解决Java并发修改异常ConcurrentModificationException(转载)

    原文地址:https://www.jianshu.com/p/f3f6b12330c1 理解和解决Java并发修改异常ConcurrentModificationException 不知读者在Java ...

  6. host mysql server_解决服务器连接错误Host ‘XXX’ is not allowed to connect to this MySQL server...

    解决服务器连接错误Host 'XXX' is not allowed to connect to this MySQL server问题,有碰到此问题的同学可进入参考. 这段时间在研究火车头的入库教程 ...

  7. 服务器集群技术(备份服务器方案和均摊工作方案)(用来解决服务器挂掉问题)...

    服务器集群技术(备份服务器方案和均摊工作方案)(用来解决服务器挂掉问题) 一.总结 1.在一个集群里面,比如老大因为莫名其妙的原因挂掉了,集群监测到老大挂掉了直接给他断掉电源(等待维修),然后让老二上 ...

  8. 深入理解全局编录服务器GC

    概述:    在Win2003AD域环境中,除了FSMO操作主机角色外,全局编录服务器(GC)也是有着特殊含义的域控制器.通过GC,可以提高在活动目录中搜索对象的速度,可以加快用户登录验证等.    ...

  9. 跨域问题深入理解以及解决办法

    跨域问题深入理解以及解决办法 参考文章: (1)跨域问题深入理解以及解决办法 (2)https://www.cnblogs.com/mhtss/p/9355956.html (3)https://ww ...

最新文章

  1. 如果你没用过maven的install,你应该了解一下!maven中的install功能及用法。
  2. Reddit 票选:2019 年绝对不能错过的机器学习论文
  3. 最大公共子串提取“模式”
  4. Delphi与c++ 数据类型对照表(从万一的博客园摘录)
  5. neo4j 两个点创建关系_Neo4j:找到两个纬度/经度之间的中间点
  6. 终端I/O之行控制函数
  7. java indexof效率_Java indexOf函数比Rabin-Karp更有效吗?文字搜寻效率
  8. Centos7 Apache 2.4.18编译安装
  9. ONNX系列四 --- 使用ONNX使TensorFlow模型可移植
  10. Focal Loss for Dense Object Detection(RetinaNet)(代码解析)
  11. 如何用敏捷搞垮一个IT团队?
  12. 【AtCoder010】A - Addition(奇偶)
  13. qq手机令牌 for android3.3 官方安装版,原QQ安全助手|QQ手机管家 for Android 安卓版v3.3.0 - PC6安卓网...
  14. 使用H-lua框架制作魔兽争霸地图(8-物编-物品绑定技能篇1)
  15. 发光二极管pcb封装图画法_电子电工如何判断发光二极管正负极,工程师教你7种方法,长见识...
  16. 英语听力计算机教室,每日英语听力电脑版|每日英语听力 v9.2.0 PC客户端
  17. Mac上使用docker环境进行C++开发的实践
  18. RabbitMQ安装过程(Win10)
  19. 科普|AGV自动运输车的不同导航方式以及优缺点
  20. 斐波那契数列编程C语言

热门文章

  1. Python——矩阵求逆、矩阵的转置
  2. 企业微信消息多久可以撤回?企业微信怎么查看撤回的消息?
  3. 【图片新闻】五角大楼的国防创新部DIU正在规划建设一个未来机器人空间站
  4. 【信息安全技术】实验报告:木马及远程控制技术
  5. android metal api,Metal简述与常用API
  6. [转]基于SNMP的MIB库访问实现的研究
  7. Python(py3fdfs)上传到fastdfs配置store_serv.ip_addr问题
  8. Mars 模拟器编写 mips32 汇编 的入门教程
  9. 使用navicat新建sqlite数据库
  10. Python | 分析txt文档特定词汇的词频,以《天龙八部》为例