linux 之 服务器关于TIME_WAIT

2023-05-16

TIME_WAIT

服务端大量处于 TIME_WAIT 状态连接的原因

TCP 四次挥手的流程

下面这个图,是由「客户端」作为「主动关闭方」的 TCP 四次挥手的流程。
在这里插入图片描述
从上图我们可以知道,TIME_WAIT 状态是「主动关闭连接方」才会出现的状态。而且 TIME_WAIT 状态会持续 2MSL 时间才会进入到 close 状态。在 Linux 上 2MSL 的默认时长是 60 秒,也就是说停留在 TIME_WAIT 的时间为固定的 60 秒。

为什么需要 TIME_WAIT 状态?

  • 保证「被动关闭连接」的一方,能被正确的关闭
  • 防止历史连接中的数据,被后面相同四元组的连接错误的接收

总之记住,谁先关闭连接的,它就是主动关闭方,那么 TIME_WAIT 就会出现在主动关闭方。

什么场景下服务端会主动断开连接呢?

第一个场景:HTTP 没有使用长连接

HTTP/1.0 中默认是关闭的,如果浏览器要开启 Keep-Alive,它必须在请求的 header 中添加

Connection: Keep-Alive

然后当服务器收到请求,作出回应的时候,它也被添加到响应中 header 里。
这样做,TCP 连接就不会中断,而是保持连接。当客户端发送另一个请求时,它会使用同一个 TCP 连接。这一直继续到客户端或服务器端提出断开连接。

HTTP/1.1 开始, 就默认是开启了 Keep-Alive现在大多数浏览器都默认是使用 HTTP/1.1
如果要关闭 HTTP Keep-Alive,需要在 HTTP 请求或者响应的 header 里添加 Connection:close 信息,也就是说,只要客户端和服务端任意一方的 HTTP header 中有 Connection:close 信息,那么就无法使用 HTTP 长连接的机制。

根据大多数 Web 服务的实现,不管哪一方禁用了 HTTP Keep-Alive,都是由服务端主动关闭连接(只需要服务器不用时直接关闭即可)。

总结
因此,当服务端出现大量的 TIME_WAIT 状态连接的时候,可以排查下是否客户端和服务端都开启了 HTTP Keep-Alive

第二个场景:HTTP 长连接超时

配置长连接的超时参数,以nginx为例:

保持和client的长连接:
http {
keepalive_timeout 120s 120s;
keepalive_requests 10000;
}

#语法
keepalive_timeout timeout [header_timeout];

第一个参数:设置keep-alive客户端(浏览器)连接在服务器端(nginx端)保持开启的超时值(默认75s);值为0会禁用keep-alive客户端连接;
第二个参数:可选、在响应的header域中设置一个值“Keep-Alive: timeout=time”;通常可以不用设置;

keepalive_timeout 针对的是浏览器和nginx建立的一个tcp通道,没有数据传输时最长等待该时候后就关闭。
nginx和upstream中的keepalive_timeout则受到tomcat连接器的控制,tomcat中也有一个类似的keepalive_timeout参数

keepalive_requests 用于设置一个keep-alive连接上可以服务的请求的最大数量,当最大请求数量达到时,连接被关闭。默认是100。这个参数就是下面第三个场景需要配置的参数。

第三个场景:HTTP 长连接的请求数量达到上限

Web 服务端通常会有个参数,来定义一条 HTTP 长连接上最大能处理的请求数量,当超过最大限制时,就会主动关闭连接。

http {
    upstream  BACKEND {
        server   192.168.0.1:8080  weight=1 max_fails=2 fail_timeout=30s;
        server   192.168.0.2:8080  weight=1 max_fails=2 fail_timeout=30s;
        keepalive 300;        // 这个很重要!最大空闲连接数,超过这个数值后就被关闭了,一般为最大连接数的10%--30%,或者直接设置最大连接数也行
    }
server {
        listen 8080 default_server;
        server_name "";
        location /  {
            proxy_pass http://BACKEND;
            proxy_set_header Host  $Host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            add_header Cache-Control no-store;
            add_header Pragma  no-cache;
            proxy_http_version 1.1;         // 这两个最好也设置
            proxy_set_header Connection "Keep-Alive";
        }
    }
}

总结
导致 nginx端出现大量TIME_WAIT的情况有两种:

  • keepalive_requests设置比较小,高并发下超过此值后nginx会强制关闭和客户端保持的keepalive长连接;(主动关闭连接后导致nginx出现TIME_WAIT
  • keepalive设置的比较小(空闲数太小),导致高并发下nginx会频繁出现连接数震荡(空闲连接数超过该值就会被关闭),不停的关闭、开启和后端server保持的keepalive长连接;

解决TIME_WAIT方法

1. 开启端口重用

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps=1(默认即为 1)

2. net.ipv4.tcp_max_tw_buckets

这个值默认为 18000,当系统中处于 TIME_WAIT 的连接一旦超过这个值时,系统就会将后面的 TIME_WAIT 连接状态重置,这个方法比较暴力。

net.ipv4.tcp_max_tw_buckets = 18000

3. 程序中使用 SO_LINGER

struct linger so_linger;
so_linger.l_onoff = 1;
so_linger.l_linger = 0;
setsockopt(s, SOL_SOCKET, SO_LINGER, &so_linger,sizeof(so_linger));

如果l_onoff为非 0, 且l_linger值为 0,那么调用close后,会立该发送一个RST标志给对端,该 TCP 连接将跳过四次挥手,也就跳过了TIME_WAIT状态,直接关闭。

但这为跨越TIME_WAIT状态提供了一个可能,不过是一个非常危险的行为,不值得提倡。

参考来源:

https://mp.weixin.qq.com/s/sK2caRVxmkXInKcxtDsTVg
https://www.cnblogs.com/grimm/p/13038577.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux 之 服务器关于TIME_WAIT 的相关文章

  • 在 C++20 中获取当前日期/时间是线程安全的吗?

    简短的问题 在 C 17 之前 包括 C 17 C 不提供线程安全的方式来获取当前时间或日期 这个问题会在 C 20 中修复吗 长问题 获取当前时间和日期的唯一可移植方法是使用 std gmtime 或 std localtime 函数 这
  • Web 应用程序的带宽和流量模拟器?

    您能否建议如何创建一个测试环境来模拟 Web 应用程序中的各种类型的带宽和流量 或者也许是一个针对本地主机执行此操作的开源程序 我认为在编写网络应用程序时这是一个非常重要的主题 但这不是一个常见的主题 我能想象创建这种环境的唯一方法是在本地
  • X11 模式对话框

    如何使用 Xlib 在 X11 中创建模式对话框 模态对话框是一个位于应用程序其他窗口之上的窗口 就像瞬态窗口一样 并且拒绝将焦点给予应用程序的其他窗口 在 Windows 中 当试图从模态窗口夺取焦点时 模态也会通过闪 烁模态窗口的标题栏
  • linux下写入后崩溃

    如果我使用 write 将一些数据写入磁盘上的文件会发生什么 但我的应用程序在刷新之前崩溃了 如果没有系统故障 是否可以保证我的数据最终会刷新到磁盘 如果您正在使用write 并不是fwrite or std ostream write 那
  • 如何使用 echo 写入非 ASCII 字符?

    如何写非ASCII http en wikipedia org wiki ASCII使用 echo 的字符 是否有转义序列 例如 012或类似的东西 我想使用以下方法将 ASCII 字符附加到文件中 echo gt gt file 如果您关
  • 从c调用汇编函数

    我试图从 c 调用汇编函数 但我不断收到错误 text globl integrate type integrate function integrate push ebp mov esp ebp mov 0 edi start loop
  • 如何将 RFC 2822 日期/时间解析为 Python 日期时间?

    我有 RFC 2822 指定的表格日期 比如说Fri 15 May 2009 17 58 28 0000 作为字符串 有没有一种快速和 或标准的方法来将其作为datetimePython 2 5 中的对象 我尝试生成 strptime 格式
  • 推荐用于小型站点的 IRC 服务器 (ircd)? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 情况 我想使用 IRC 机器人作为我正在研究的其他代码的通用通信接口 服务器硬件陈旧且内存不足 但运行在相对最新的 Debian GNU
  • 使用 WebDriver 暂时绕过隐式等待

    当使用隐式等待时 正如这里所建议的 https stackoverflow com a 10950905 56285 我仍然有时想要断言即时元素不可见或不存在 换句话说 我know有些元素应该隐藏 并希望我的测试做出这样的断言fast 而不
  • 错误:命令“c++”失败,退出状态为 1

    所以我尝试按照以下说明安装 Pyv8https andrewwilkinson wordpress com 2012 01 23 integrating python and javascript with pyv8 https andre
  • C++:Linux平台上的线程同步场景

    我正在为 Linux 平台实现多线程 C 程序 其中我需要类似于 WaitForMultipleObjects 的功能 在搜索解决方案时 我发现有一些文章描述了如何在 Linux 中实现 WaitForMultipleObjects 功能
  • XAMPP Windows 上的 Php Cron 作业

    嗯 我是这个词的新手CRON 据我所知 这是一个Unix安排特定操作在定义的时间间隔后执行的概念 我需要运行一个php文件 每小时更新一次数据库 但我的困惑在于安排执行 我在用XAMPP用于 Windows 7 上的本地开发测试 我发现了什
  • 用于读取文件的 Bash 脚本

    不知道为什么最后一行没有从脚本中删除 bin bash FILENAME 1 while read line do cut d f2 echo line done lt FILENAME cat file 1 test 2 test 3 t
  • 使用 ProcessBuilder 运行 shell 脚本

    我正在尝试使用 Java 和 ProcessBuilder 运行脚本 当我尝试运行时 我收到以下消息 error 2 没有这样的文件或目录 我不知道我做错了什么 但这是我的代码 ps 我尝试只执行不带参数的脚本 错误是相同的 String
  • 使用c在linux上分块读写

    我有一个 ASCII 文件 其中每一行都包含一个可变长度的记录 例如 Record 1 15 characters Record 2 200 characters Record 3 500 characters Record n X cha
  • 在 Linux 控制台中返回一行?

    我知道我可以返回该行并用以下内容覆盖其内容 r 现在我怎样才能进入上一行来改变它呢 或者有没有办法打印到控制台窗口中的特定光标位置 我的目标是使用 PHP 创建一些自刷新的多行控制台应用程序 Use ANSI 转义码 http en wik
  • SMP 上如何处理中断?

    SMP 对称多处理器 多核 机器上如何处理中断 内存管理单元是只有一个还是多个 假设两个线程 A 和 B 运行在不同的内核上 同时 访问页表中不存在的内存页面 在这种情况下 将会出现页面错误 并从内存中引入新页面 将会发生的事件的顺序是什么
  • 如何列出 nginx 中的所有虚拟主机

    有没有一个命令可以列出 CentOS 上 nginx 下运行的所有虚拟主机或服务器 我想将结果通过管道传输到文本文件以用于报告目的 我正在寻找与我用于 Apache 的命令类似的命令 apachectl S 2 gt 1 grep 端口 8
  • 在非实时操作系统/内核上执行接近实时任务的最佳方法是什么?

    在一台 GNU Linux 机器上 如果想要执行 实时 亚毫秒级时间关键 任务 您几乎总是必须经历漫长 复杂且容易出现问题的内核补丁过程 以提供足够的支持 1 http en wikipedia org wiki RTLinux Backg
  • 为什么默认情况下不启用 arp 忽略/通告 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我有一个需要经验才能回答的具体问题 为什么 arp ignore arp announce 在 Linux 安装 例如 debian 上默认不启用 有

随机推荐

  • 进程和线程的区别与联系

    1 共同点 功能上都是用于实现多任务并发程序设计的技术手段 xff0c 线程的状态包括就绪 执行与阻塞 xff0c 与进程类似 从系统实现的角度看 xff0c 进程实体和线程实体在Linux内核中都是有task struct实现的 xff0
  • AD9的pcb 里面怎样才能从TOP层视图换成从BOTTOM层网上面看,相当于把板子翻过来看

    AD9中更改PCB的视角 切换到3D xff08 view gt switch To 3D xff09 视图 xff0c 然后点击 view gt Orthogonal Rotation 然后在切换到2D视图 xff08 view gt s
  • opencv中三种像素访问方式的运行速度比较

    本文目的 xff1a 在opencv中有三种方式可以读写图像的像素 xff0c 分别为 xff1a 指针读写 迭代器读写 动态地址计算读写 虽然三种方式都可以完成同样的目的 xff0c 但是运行速度却有快有慢 xff0c 尤其是在实现一些复
  • 如何确认系统是采用大端还是小端

    如何确认系统是采用大端还是小端 1 大小端 大端 xff08 存储 xff09 模式 xff1a 是指一个数据的低位字节序的内容放在高地址处 xff0c 高位字节序存的内容放在低地址处 如 xff1a 一个数0x12345678存放在一个4
  • C++ Primer Plus 第六版 所有章节课后编程练习答案

    我的独立博客地址 xff1a www blog4jimmy com xff0c 欢迎大家关注 下面的是C 43 43 Primer Plus 第六版所有章节的课后编程练习的答案 xff0c 都是博主自己写的 xff0c 有不对的地方请大家留
  • 串口发送大数组

    用stm32f4XX发送采集到的数据时 xff0c 如果数据量特别大 xff0c 直接发送一个大数组可能比较占内存 这时候 xff0c 可以逐个发送数据 最好将大数组定义为全局变量 定义在函数内时 xff0c 可能导致栈不够深而报错 其模式
  • IP数据包校验过程

    1 算法思路 xff1a IP ICMP IGMP TCP UDP等协议的校验和算法都是相同的 xff0c 算法如下 xff1a 在发送数据时 xff0c 为了计算IP数据包的校验和 应该按如下步骤 xff1a xff08 1 xff09
  • CMake 和makefile

    1 gcc 它是GNU Compiler Collection xff08 就是GNU编译器套件 xff09 xff0c 也可以简单认为是编译器 xff0c 它可以编译很多种编程语言 xff08 括C C 43 43 Objective C
  • ROS CMakeLists中target_link_libraries相对路径设置

    希望大家收藏 xff1a 本文更新地址 xff1a https haoqchen site 2018 04 26 CMakeLists setting relative path 左侧专栏还在更新其他ROS实用技巧哦 xff0c 关注一波
  • AD10 复制问题(复制方法和智能粘贴 拼版)

    ad10PCB复制不成功 频繁的遇到过在PCB界面复制不成功的情况 xff0c 今天终于搞明白了是什么原因造成的 当我们选中元件的时候 xff0c 鼠标箭头就会有一个十字架的形状 xff0c 这时候直接按下CTRL 43 C然后再在其他的地
  • Postman中文版,竟如此简单,秒变中文

    好多小伙伴 xff0c 尤其是刚入门软件测试的 xff0c 对英文版本的Postman很抵触 xff0c 希望有个中文版的 xff0c 不过很遗憾的是Postman只有英文版本 xff0c 但凡事都有例外 xff0c 某天在逛github的
  • Http协议报文格式

    一 整体介绍 Http协议在传输层基于TCP协议 xff0c 在Http1 1之前每次请求在TCP层都需进行一轮连接和释放 xff08 三次握手 四次握手 xff09 xff0c 从Http1 1开始默认使用长连接 Http报文分为两种 x
  • 记录一次json_decode 返回NULL解决过程

    后台返回数据 xff0c 前端收到数据之后 xff0c 在调用json decode 之后 xff0c 返回null 用json last error 报错 3 在解码前 xff0c 对字符串进行处理 data 61 preg replac
  • mybatis-plus之saveBatch开启批量插入

    背景 MyBatis Puls的saveBatch默认并没有批量添加 xff0c 实际上在插入的时候仍然是一条条记录的插 开启 在jdbc的url连接参数中添加 rewriteBatchedStatements 61 true
  • PHP 之 问题记录一

    临时设置时区 date default timezone set 39 PRC 39 获取当前毫秒数 span class token comment 1670834581421 span span class token keyword
  • HTTPS 之 请求头缺少HTTPOnly和Secure属性解决方案

    1 如果使用php 修改 php ini 的 session cookie httponly 和 session cookie secure 为 1 xff0c 重启php 2 如果使用nginx nginx conf 文件中设置 http
  • Linux 之 恢复删除文件

    方法一 如果进程ID还存在 xff0c 可以直接恢复 span class token number 1 span lsof span class token operator span span class token function
  • mybatis-plus 之 find_in_set使用

    MP中使用find in set函数 span class token class name LambdaQueryWrapper span span class token generics span class token punctu
  • springboot 之 常用jackson配置

    时区 spring jackson time zone 61 GMT 43 8 日期格式 spring jackson date format 61 yyyy MM dd HH mm ss 默认转json的属性 xff0c 这里设置为非空才
  • linux 之 服务器关于TIME_WAIT

    TIME WAIT 服务端大量处于 TIME WAIT 状态连接的原因 TCP 四次挥手的流程 下面这个图 xff0c 是由 客户端 作为 主动关闭方 的 TCP 四次挥手的流程 从上图我们可以知道 xff0c TIME WAIT 状态是