为了能彻底讲清楚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 为一个较小的值

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

办法5. 打开tcp_tw_reuse和tcp_timestamps选项

官方文档中解释如下:
tcp_tw_recycle选项:Allow to reuse TIME-WAIT sockets for new connections when it is
safe from protocol viewpoint. Default value is 0

这里的关键在于“协议什么情况下认为是安全的”,由于环境限制,没有办法进行验证,通过看源码简单分析了一下

=====linux-2.6.37 net/ipv4/tcp_ipv4.c 114=====

int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
{const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);struct tcp_sock *tp = tcp_sk(sk);/* With PAWS, it is safe from the viewpointof data integrity. Even without PAWS it is safe provided sequencespaces do not overlap i.e. at data rates <= 80Mbit/sec.Actually, the idea is close to VJ's one, only timestamp cache isheld not per host, but per port pair and TW bucket is used as stateholder.If TW bucket has been already destroyed we fall back to VJ's schemeand use initial timestamp retrieved from peer table.*///从代码来看,tcp_tw_reuse选项和tcp_timestamps选项也必须同时打开;否则tcp_tw_reuse就不起作用//另外,所谓的“协议安全”,从代码来看应该是收到最后一个包后超过1sif (tcptw->tw_ts_recent_stamp &&(twp == NULL || (sysctl_tcp_tw_reuse &&get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;if (tp->write_seq == 0)tp->write_seq = 1;tp->rx_opt.ts_recent  = tcptw->tw_ts_recent;tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;sock_hold(sktw);return 1;}return 0;
}

总结一下:
1. tcp_tw_reuse选项和tcp_timestamps选项也必须同时打开;
2. 重用TIME_WAIT的条件是收到最后一个包后超过1s。

官方手册有一段警告:
It should not be changed without advice/request of technical experts.
对于大部分局域网或者公司内网应用来说,满足条件都是没有问题的,因此官方手册里面的警告其实也没那么可怕

办法6:设置tcp_max_tw_buckets为一个较小的值,要比可用端口范围小,比如可用端口范围为6万,这个值可以设置为5.5万

tcp_max_tw_buckets - INTEGER

官方文档解释如下
Maximal number of timewait sockets held by system simultaneously. If this number is exceeded time-wait socket is immediately destroyed and warning is printed.

翻译一下:内核持有的状态为TIME_WAIT的最大连接数。如果超过这个数字,新的TIME_WAIT的连接会被立即销毁,并打印警告

官方文档没有说明默认值,通过几个系统的简单验证,初步确定默认值是180000

源码如下

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;if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp)recycle_ok = icsk->icsk_af_ops->remember_stamp(sk);// 这里判断TIME_WAIT状态的连接数是否超过上限if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets)tw = inet_twsk_alloc(sk, state);if (tw != NULL) {//分配成功,进行TIME_WAIT状态处理,此处略去很多代码}   else {//分配失败,不进行处理,只记录日志: TCP: time wait bucket table overflow/* Sorry, if we're out of memory, just CLOSE this* socket up.  We've got bigger problems than* non-graceful socket closings.*/NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEWAITOVERFLOW);}tcp_update_metrics(sk);tcp_done(sk);
}

官方手册中有一段警告:
This limit exists only to prevent simple DoS attacks, you _must_ not lower the limit artificially,
but rather increase it (probably, after increasing installed memory), if network conditions require more than default value.
基本意思是这个用于防止Dos攻击,我们不应该人工减少,如果网络条件需要的话,反而应该增加。
但其实对于我们的局域网或者公司内网应用来说,这个风险并不大

彻底理解并解决服务器出现大量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. 深入理解Tomcat和Jetty源码之第四篇tomcat系统架构上:容器是如何设计的

    今天来介绍一下Tomcat的容器机制: 1.Tomcat的四种容器 2.容器示意图 3.责任链模式介绍 4.Tomcat如何确定请求是哪个Wrapper处理的 5.Tomcat的Context和ser ...

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

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

  5. 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问题,有碰到此问题的同学可进入参考. 这段时间在研究火车头的入库教程 ...

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

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

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

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

  8. graphics2d 乱码 java_java Graphics2D绘制文字并居中并解决服务器乱码问题

    java Graphics2D绘制文字并居中并解决服务器乱码问题 package com.test.testImage; import java.awt.Color; import java.awt. ...

  9. 解决服务器被黑上不了网的问题

    SWATCH swatch命令:系统监控程序 TLOAD tload命令:显示系统负载 Uname:显示系统信息 Top:显示进程信息 Whoami命令 :显示用户名 Whois命令:显示指定用户信息 ...

最新文章

  1. MPB:林科院袁志林组-一种简易的植物组织表面消毒装置
  2. 没中、美这么大的统一市场,欧盟人工智能发展面临双重挑战
  3. 【 SIMULATION 】RMSE Comparison of Linear Approaches for TOA - Based Positioning
  4. Windows 搭建ASP.NET Boilerplate项目开发环境
  5. python项目归纳总结-这4个Python实战项目,让你瞬间读懂Python!
  6. ​​​​​​​Git学习笔记与IntelliJ IDEA整合
  7. Windows via C/C++ 学习(15)线程调度、线程优先级和亲缘性
  8. MySQL的FROM_UNIXTIME()和UNIX_TIMESTAMP()函数
  9. python能写什么脚本_你用 Python 写过哪些有趣的脚本?
  10. 创建虚拟磁盘的小工具软件plainmaker.exe
  11. jQuery1.3.2 源码学习 -2 两个重要的正则表达式
  12. 为什么iPhone 11在中国市场需求较美国强劲?真相扎心...
  13. C++知识点总结(三)
  14. MapReduce 学习指南
  15. java中接口与抽象类的区别
  16. java 虚拟机内存不足_JAVA虚拟机内存不够解决办法
  17. 北大清华人大中关村周围二手书店淘书全攻略
  18. wd移动硬盘不能识别_wd移动硬盘xp无法识别 移动硬盘无法识别的解决方法
  19. Scheme 协议收集总结
  20. 算法创作|什么是数据结构

热门文章

  1. 机器学习之数学系列(二)梯度下降法(参数更新公式的由来)
  2. 唯众职教学生实训系统
  3. 中文select按照字母a-z排序
  4. osg开发配置与第一个osg程序
  5. STM32F407-限位金属传感器限制步进电机
  6. python 调用event handler_扣丁学堂Python开发之调用语音模块时报错及解决方法
  7. java微信测试公众号实现文本、图片消息回复
  8. 合肥工业大学计算机与信息工程学院,合肥工业大学计算机与信息学院导师介绍:开彩红...
  9. 计算机原理探究第一部分教案,计算机系统的组成部分教案.doc
  10. 学习淘淘商城第八十七课(单点登录用户登录流程分析及用户登录Service层)