服务压测发现怪异现象,一顿排查,揪出“TIME_WAIT”这个内鬼
点击关注公众号,Java干货及时送达
最近有同事在用 ab 进行服务压测,到 QPS 瓶颈后怀疑是起压机的问题,来跟我借测试机,于是我就趁机分析了一波起压机可能成为压测瓶颈的可能,除了网络 I/O、机器性能外,还考虑到了网络协议的问题。
当然本文的主角并不是压测,后来分析证明同事果然还是想多了,瓶颈是在服务端。
分析起压机瓶颈的过程中,对于 TCP TIME_WAIT 状态的一个猜想引起了我的兴趣。由于之前排查问题时,简单地接触过这个状态,但并未深入了解,于是决定抽时间分析一下,拆解一下我的猜想。
TCP 的状态转换
我们都知道 TCP 的三次握手,四次挥手,说来简单,但在不稳定的物理网络中,每一个动作都有可能失败,为了保证数据被有效传输,TCP 的具体实现中也加入了很多对这些异常状况的处理。
状态分析
先用一张图来回想一下 TCP 的状态转换。
一眼看上去,这么多种状态,各个方向的连线,让人感觉有点懵。但细细分析下来,还是有理可循的。
首先,整个图可以被划分为三个部分,即上半部分建连过程,左下部分主动关闭连接过程和右下部分被动关闭连接过程。
再来看各个部分:建连过程就是我们熟悉的三次握手,只是这张图上多了一个服务端会存在的 LISTEN 状态;而主动关闭连接和被动关闭连接,都是四次挥手的过程。
查看连接状态
在 Linux 上,我们常用 netstat
来查看网络连接的状态。当然我们还可以使用更快捷高效的 ss
(Socket Statistics) 来替代 netstat。
这两个工具都会列出此时机器上的 socket 连接的状态,通过简单的统计就可以分析出此时服务器的网络状态。
TIME_WAIT
定义
我们从上面的图中可以看出来,当 TCP 连接主动关闭时,都会经过 TIME_WAIT 状态。而且我们在机器上 curl 一个 url 创建一个 TCP 连接后,使用 ss 等工具可以在一定时长内持续观察到这个连续处于 TIME_WAIT 状态。
所以TIME_WAIT 是这么一种状态:TCP 四次握手结束后,连接双方都不再交换消息,但主动关闭的一方保持这个连接在一段时间内不可用。
那么,保持这么一个状态有什么用呢?
原因
上文中提到过,对于复杂的网络状态,TCP 的实现提出了多种应对措施,TIME_WAIT 状态的提出就是为了应对其中一种异常状况。
为了理解 TIME_WAIT 状态的必要性,我们先来假设没有这么一种状态会导致的问题。暂以 A、B 来代指 TCP 连接的两端,A 为主动关闭的一端。
四次挥手中,A 发 FIN, B 响应 ACK,B 再发 FIN,A 响应 ACK 实现连接的关闭。而如果 A 响应的 ACK 包丢失,B 会以为 A 没有收到自己的关闭请求,然后会重试向 A 再发 FIN 包。
如果没有 TIME_WAIT 状态,A 不再保存这个连接的信息,收到一个不存在的连接的包,A 会响应 RST 包,导致 B 端异常响应。
此时, TIME_WAIT 是为了保证全双工的 TCP 连接正常终止。
我们还知道,TCP 下的 IP 层协议是无法保证包传输的先后顺序的。如果双方挥手之后,一个网络四元组(src/dst ip/port)被回收,而此时网络中还有一个迟到的数据包没有被 B 接收,A 应用程序又立刻使用了同样的四元组再创建了一个新的连接后,这个迟到的数据包才到达 B,那么这个数据包就会让 B 以为是 A 刚发过来的。
此时, TIME_WAIT 的存在是为了保证网络中迷失的数据包正常过期。
由以上两个原因,TIME_WAIT 状态的存在是非常有意义的。
时长的确定
由原因来推实现,TIME_WAIT 状态的保持时长也就可以理解了。确定 TIME_WAIT 的时长主要考虑上文的第二种情况,保证关闭连接后这个连接在网络中的所有数据包都过期。
说到过期时间,不得不提另一个概念: 最大分段寿命(MSL, Maximum Segment Lifetime),它表示一个 TCP 分段可以存在于互联网系统中的最大时间,由 TCP 的实现,超出这个寿命的分片都会被丢弃。
TIME_WAIT 状态由主动关闭的 A 来保持,那么我们来考虑对于 A 来说,可能接到上一个连接的数据包的最大时长:A 刚发出的数据包,能保持 MSL 时长的寿命,它到了 B 端后,B 端由于关闭连接了,会响应 RST 包,这个 RST 包最长也会在 MSL 时长后到达 A,那么 A 端只要保持 TIME_WAIT 到达 2MS 就能保证网络中这个连接的包都会消失。
MSL 的时长被 RFC 定义为 2分钟,但在不同的 unix 实现上,这个值不并确定,我们常用的 centOS 上,它被定义为 30s,我们可以通过 /proc/sys/net/ipv4/tcp_fin_timeout
这个文件查看和修改这个值。
ab 的”奇怪”表现
猜想
由上文,我们知道由于 TIME_WAIT 的存在,每个连接被主动关闭后,这个连接就要保留 2MSL(60s) 时长,一个网络四元组也要被冻结 60s。而我们机器默认可被分配的端口号约有 30000 个(可通过 /proc/sys/net/ipv4/ip_local_port_range
文件查看)。
那么如果我们使用 curl 对服务器请求时,作为客户端,都要使用本机的一个端口号,所有的端口号分配到 60s 内,每秒就要控制在 500 QPS,再多了,系统就无法再分配端口号了。
可是在使用 ab 进行压测时时,以每秒 4000 的 QPS 运行几分钟,起压机照样正常工作,使用 ss 查看连接详情时,发现一个 TIME_WAIT 状态的连接都没有。
分析
一开始我以为是 ab 使用了连接复用等技术,仔细查看了 ss 的输出发现本地端口号一直在变,到底是怎么回事呢?
于是,我在一台测试机启动了一个简单的服务,端口号 8090,然后在另一台机器上起压,并同时用 tcpdump 抓包。
结果发现,第一个 FIN 包都是由服务器发送的,即 ab 不会主动关闭连接。
登上服务器一看,果然,有大量的 TIME_WAIT 状态的连接。
但是由于服务器监听的端口会复用,这些 TIME_WAIT 状态的连接并不会对服务器造成太大影响,只是会占用一些系统资源。
小结
当然,高并发情况下,太多的 TIME_WAIT 也会给服务器造成很大的压力,毕竟维护这么多 socket 也是要消耗资源的。
来源 | https://zhenbianshu.github.io/
热门内容:CTO 说了,如果发现谁用 kill -9 关闭程序就开除
面试官问:MySQL 的自增 ID 用完了,怎么办?
王者荣耀中一个英雄是怎么被产生的?
饿了么CTO:“不能被烂用的框架不是好框架”!
最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ♡
服务压测发现怪异现象,一顿排查,揪出“TIME_WAIT”这个内鬼相关推荐
- 服务压测发现怪异现象,一顿排查,揪出“TIME_WAIT”这个内鬼~
点击关注公众号,回复"2T"获取2TB学习资源! 互联网架构师后台回复 2T 有特别礼包 上一篇:深夜看了张一鸣的微博,让我越想越后怕 来源:https://zhenbianshu ...
- 如何使用 PTS 快速发起微服务压测
作者:亦炎 什么是微服务 通常而言,微服务架构是一种架构模式或者说是一种架构风格. 本文阐述了: 什么是微服务架构 微服务架构对系统稳定性带来的影响,以及用性能测试验证稳定性的必要性 用户进行微服务压 ...
- 登录接口压测响应慢频繁GC问题排查
登录接口压测响应慢频繁GC问题排查 2020.5.22 最近项目组针对几个较重要的接口进行了几十个小时的压测,发现登录接口的压测呈现了一种响应慢且越来越慢的趋势,CPU 也居高不下 压测情况 查看CP ...
- dubbo 服务压测_不可忽视的Dubbo线程池
问题描述 线上突然出现Dubbo超时调用,时间刚好为Consumer端设置的超时时间. 有好几个不同的接口都报超时了 第1次调用超时,第2次(或第3次)重试调用非常快(正常水平) Dubbo调用超时的 ...
- Web服务压测神器wrk
wrk是一款开源的高性能http压测工具(也支持https),非常小巧,可以执行文件只有3M(其中主要是luajit和openssl占用绝大多数空间),别看核心代码3-5年没更新了,但依旧非常好用.虽 ...
- web版本 开源压测工具_Web服务压测神器wrk
wrk是一款开源的高性能http压测工具(也支持https),很是小巧,能够执行文件只有3M(其中主要是luajit和openssl占用绝大多数空间),别看核心代码3-5年没更新了,但依旧很是好用.虽 ...
- dubbo 服务压测_全链路压测资料汇总——业内大厂解决方案
最近忙于公司的全链路压测平台调研和技术规划文档输出工作,参考了全网能搜到的业内大厂的全链路压测方案,这里做个汇总,以及将个人认为可以落地的方案做一个关键点整理. 技术链接 滴滴全链路压测解决之道 阿里 ...
- Beetlex之websocket/tls服务压测工具
为了方便压力测试ws服务,Beetlex同样提供相关工具来对ws/wss服务的性能进行测试测试. 安装 可以访问https://github.com/beetlex-io/TCPBenchmarks ...
- Beetlex之tcp/tls服务压测工具
在编写tcp服务的时候经常需要对服务的基础性能进行一个压力测试,虽然网上这些工具有很多,但具备使用方便和高强度的测试工具则不多.为了方便这方面的高强度压测所以在beetlex的基础扩展这样一个工具. ...
最新文章
- 路印协议受邀参加澳洲新南威尔士政府孵化器Haymarket HQ分享论坛
- Spring boot表单提交日期格式
- Python实现顺序表
- [bbk5307]第76集 第9章 -数据库性能维护 03
- python 生成器推导式
- WordPress程序备受喜爱的原因:十八般武艺(3)
- 剑指offer(C++)-JZ22:链表中倒数最后k个结点(数据结构-链表)
- hdu 畅通工程再续
- 免费在upic中设置OneDrive或Google Drive作为图床
- antd table组件 表格内换行
- CF1654-G. Snowy Mountain(2900) GOOD
- 灵魂画师全都出来了,都怪昨天那个AI画猫的应用……
- 【lifelines中文wiki】生存分析简介
- linux系统深度评测,真国产,深度linux系统评测第二集
- 【雷达与对抗】【2017.06】空中目标的无源雷达探测
- @Dan Abramov:我的十年回顾
- Android 广告秘籍
- 畅聊微信支付遇到的坑
- mysql怎么定位cpu高_Mysql数据库服务器CPU冲高问题定位及分析
- 多媒体 MP4文件格式详解——文件类型ftyp