压力测试遭遇大量TIME_WITE之后(这样解决)

news2024/11/18 5:08:04

前言:http协议是互联网中最常使用的应用层协议,它的绝大多数实现是基于TCP协议的。

目录

一 问题描述

二 问题跟踪

三 跟进分析

四 解决方法


一、问题描述

某天,在对一个提供http接口的后台服务进行压力测试过程中,我们设定了几百qps(每秒请求数)开始测试几分钟后,请求一端(我们后续简称为:客户端)的压力结果统计日志中开始连续出现大量的报错信息:

图1-压力测试请求中出现大量报错

在压力测试前,根据之前的经验,同类服务的单机性能一般能够达到几千QPS,然而此时测试设定的压力值还不足200qps,这与预期存在1个数量级以上的性能差距,难道是被测服务存在问题么?

二、问题跟踪

为了确认被测服务的状态,我们首先登录了服务所在的机器,检查了服务资源的占用情况,结果是:CPU、内存、硬盘、I/O、网卡、fd、socket等各项资源都不存在较大负载。看来服务本身还远没有达到它的负载瓶颈。

在排除服务端问题后,我们重新分析了统计日志中的错误--"can not assign requested address",这是一个常见的socket的error,报错信息说明无法为socket创建新的连接,很可能是:tcp层的连接端口已经耗尽,无法为新的http请求分配端口建立连接。通过netstat命令,我们检查客户端,发现确实存在大量请求连接处于TIME_WAIT状态下:

图2-请求机器中tcp连接状态统计

这里要说明一下,虽然理论上tcp连接可用端口号为0~65535--大约65536个,但是实际在不指定端口情况下连接服务时可用端口默认为32768~61000--大约只有28000多个,在linux系统中这个限制可以通过/proc/sys/net/ipv4/ip_local_port_range文件进行修改。

我们知道http协议主要是基于tcp协议之上的,为了解决tcp层连接通道复用的问题,在http协议中通过header中的Connection字段定义了对于tcp长连接的支持:

  • 在HTTP/1.0版本中,默认情况下在HTTP1.0中所有连接不被保持,如果客户端浏览器支持Keep-Alive,那么就在HTTP请求头中添加一个字段 Connection: Keep-Alive,当服务器收到附带有Connection: Keep-Alive的请求时,它也会在响应头中添加一个同样的字段来使用Keep-Alive。这样一来,客户端和服务器之间的HTTP连接就会被保持,当客户端发送另外一个请求时,就使用这条已经建立的连接通道。
  • 在HTTP/1.1版本中,默认情况下在HTTP1.1中所有连接都会被保持,除非在请求头或响应头中指明要关闭:Connection: Close,这也就是为什么Connection: Keep-Alive字段再没有意义的原因。

在压力测试过程中,我们模拟发送http请求的代码中使用的是http/1.1协议,应该会默认使用长连接,看来很可能是服务端不支持长连接,才会引起客户端频繁的创建TCP连接。通过tcpdump抓包,我们对此进行了证实:

图3-wireshark分析http响应信息

三、跟进分析

到此,我们发现服务端确实返回不支持长连接的信息(header中connection:close),导致客户端每次发起请求都会重新创建tcp通道。但是根据以往测试经验来看,比较常见的是在服务端出现大量time_wait状态的,那么为什么大量的time_wait状态会在客户端出现呢?

了解这个问题我们之前,可以先来看一下TCP正常连接建立和关闭连接时的状态变化图:

图4-tcp正常连接建立和终止所对应的状态图

上图是TCP"三次握手"和"四次挥手"的过程,相信很多读者都比较了解,下面我们来说说为什么要存在TIME_WAIT状态吧:

  • 可靠地实现TCP全双工连接的终止--TCP协议在关闭连接的四次挥手中,在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。
  • 允许老的报文段在网络中消失--TCP报文段可能由于路由器异常而“迷路”,在迷途期间,TCP发送端可能因确认超时而重发这个报文,迷途的报文在路由器修复后也会被送到最终目的地,这个原来的迷途报文就称为lost duplicate。在关闭一个TCP连接后,马上又重新建立起一个相同的IP地址和端口之间的TCP连接,后一个连接被称为前一个连接的化身 (incarnation),那么有可能出现这种情况,前一个连接的迷途重复报文在前一个连接终止后出现,从而被误解成从属于新的化身。为了避免这个情 况,TCP不允许处于TIME_WAIT状态的连接启动一个新的化身,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时候,来自连接先前化身的重复报文已经在网络中消逝。

明白了time_wait的存在原因和出现时机,可以得到一个结论:TIME_WAIT状态总是出现的主动关闭连接的一方,也就是说在我们压力测试过程中每次都是客户端主动关闭tcp连接的。从实际的抓包结果来看,确实如此:

图5-wireshark分析TCP关闭过程

但是我们实际遇到的多是time_wait出现在服务一端出现的,那么在http协议规定中,服务端返回connection:close的信息后,到底是应该由客户端还是服务端来主动关闭连接呢?

Connection: close 是一个 general-header( RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1 )即:既可以作为 request header 也可以作为 response header。Connection: close 的作用在于"协商(signal)"。在RFC2616 14.10 中:HTTP/1.1 defines the "close" connection option for the sender to signal that the connection will be closed after completion of the response.

通过RFC可以发现:请求和响应的双方都可以主动关闭TCP连接。

但是大多数的web Service实现是返回connection:close内容之后服务端会主动关闭连接。至于这样设计的原因,网上找到2个比较靠谱的解释:

  • server 主动关闭连接是历史原因:HTTP/0.9 协议中 response 是没有 header 的,所以 client 根本无从知道什么时候这个东西结束。
  • 在server 主动关闭连接的情况下,只要调用一次 close() 就可以释放连接,剩下的工作由内核 TCP 栈直接进行了处理,整个过程只有一次 syscall;如果是要求 client 关闭,则 server 在写完最后一个 response 之后需要把这个 socket 放入 readable 队列,调用 select / epoll 去等待事件;然后调用一次 read() 才能知道连接已经被关闭,这其中是两次 syscall,多一次用户态程序被激活执行,而且 socket 保持时间也会更长②;

也许会有读者担心:如果客户端也不主动关闭TCP连接,服务端的socket资源会不会很快用完呢。这里留给读者们一个问题进行思考:在单个服务器上的服务端理论上能支持的最大TCP连接数是多少呢?

四、解决方法

根据分析,我们知道了客户端请求报错的原因在于:服务端拒绝了客户端的HTTP长连接请求,同时服务端没有主动关闭tcp连接,而是由客户端主动关闭网络连接,导致在客户端出现大量time_wait,在压测进行到一段时候后由于没有新的socket端口可用而开始报错。

了解了原因后,解决方法就比较简单了,需要我们修改客户端所在linux环境下的tcp相关参数,编辑/etc/sysctl.conf文件,增加三行:

再执行以下命令,让修改结果立即生效即可:

/sbin/sysctl -p #从配置文件“/etc/sysctl.conf” 加载内核参数设置

然后,我们的压力测试的客户端就不会再受time_wait问题困扰了。

结语

这篇贴子到这里就结束了,最后,希望看这篇帖子的朋友能够有所收获。

如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

性能测试【性能测试介绍及价值和目的】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/611503.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

科班出身又如何?这类人连外包都不要...

在软件测试这个领域,多数人对于外包公司是有戴有色眼镜看待的,外包测试员往往会处于一个比较尴尬的局面。主要是由于雇主公司比较核心或者底层的东西是不会让外包人员作的。外包人员一般做的都是“边角料”。而这些活往往对于技术要求不高,所…

python接口自动化 —— 接口测试工具介绍(详解)

简介 “工欲善其事必先利其器”,通过前边几篇文章的介绍,大家大致对接口有了进一步的认识。那么接下来让我们看看接口测试的工具有哪些。 目前,市场上有很多支持接口测试的工具。利用工具进行接口测试,能够提供测试效率。例如&…

运维小白必学篇之基础篇第十集:系统启动流程实验

系统启动流程实验 实验作业: 1、现在有一台服务器因为长时间不使用,管理员密码已经丢失,现在想要启动该服务器,如何操作 第一步:开启系统,在GRUB界面按E进行编辑 在linux16行中centos/swap后添加 rd.break参…

【AI】InsCode AI 创作助手 --使用心得

CSDN AI写作助手上线了!InsCode AI 创作助手不仅能够帮助用户高效创作文章,而且能够作为对话式AI回答你想知道的问题。成倍提高生产力!欢迎大家使用新功能后分享自己的使用心得与建议! 文章目录 一、你平时会使用这类AI工具吗&am…

navicat与SQLyog的区别

在之前的学习中由于先学的SQL Server,后来才学的MySQL,导致我刚学习的时候冥冥之中感觉到那有点不对劲,但是又说不出来。通过进行深入的学习解除到了Navicat Premium和SQLyog这两个工具,才让我明白了MySQL与之前学习的内容是有所出…

影响代理ip纯净度的原因及目标网站如何识别代理ip

网络上代理ip很多,但真正可以为我们所用的大部分都是付费ip,那为什么免费ip不能为我们所用呢?下面我们就纯净度和目标网站是如何识别代理ip来分析一下。 一、纯净度 ip纯净度是什么意思呢?简单一点开始就是指使用这个ip的人少&…

教你 5 分钟快速部署开源网关

最近在研究开源网关,找了一圈,发现这个叫 Apinto 的开源网关符合我的需求,下面我将演示如何部署这样一个开源网关。 Apinto功能架构图 开始部署 部署资源 设备推荐配置设备数量部署对象4核8G,250G磁盘空间,2.5GHz1控制…

SQL-基础

SQL-小基础 1 SQL简介 英文:Structured Query Language,简称 SQL结构化查询语言,一门操作关系型数据库的编程语言定义操作所有关系型数据库的统一标准对于同一个需求,每一种数据库操作的方式可能会存在一些不一样的地方&#xff…

RPC接口测试技术-Tcp 协议的接口测试

【摘要】 首先明确 Tcp 的概念,针对 Tcp 协议进行接口测试,是指基于 Tcp 协议的上层协议比如 Http ,串口,网口, Socket 等。这些协议与 Http 测试方法类似(具体查看接口自动化测试章节)&#xf…

Ingress Controller高可用部署

Ingress-controller 高可用解说 Ingress Controller 是集群流量的接入层,对它做高可用非常重要,可以基于 keepalive 实现 nginx-ingress-controller 高可用,具体实现如下: Ingress-controller 根据 Deployment nodeSeletorpod 反…

揭秘广告投放的9大关键环节,了解真相让你成为广告投放高手!

正式开始本章的内容之前,先来简单复习一下上一章的主要内容: 核心要点1:广告投放的意义主要有三点:传播品牌、宣传产品、促成转化; 核心要点2:广告投放的主要流程有这样 9 个阶段: 本章我们以…

OpenCV(图像处理)-基于Python-图像的基本变换-平移-翻转-仿射变换-透视变换

1. 概述2. 接口介绍resize()flip()rotate()仿射变换warpAffine()getRotationMatrix2D()-变换矩阵1getAffineTransform()-变换矩阵2 透视变换warpPerspective()getPerspectiveTransform() 1. 概述 为了方便开发人员的操作,OpenCV还提供了一些图像变换的API&#xff…

Qt 去除标题栏不同方法不同平台差异探究

Qt 版本:Qt 6.5.0 Windows 11 当窗体为QWidget时 setWindowFlags(Qt::FramelessWindowHint);// 窗口不能缩放setWindowFlags(Qt::CustomizeWindowHint);// 窗口支持缩放,且窗体四角为圆角CustomizeWindowHintFramelessWindowHint 当窗体为QMainWindow时…

什么是第三方付费模式?用“尤伯罗斯模式”让你的商品由别人买单

什么是第三方付费模式?用“尤伯罗斯模式”让你的商品由别人买单 微三云营销策划胡总监给大家介绍一下,什么是第三方付费模式? 当同质化产品日趋严重的时候,改变客户接受产品价值及服务的模式创新就是商业模式的创新,以…

计算机硬件(2)

1.4 计算机硬件 电脑硬件是计算机系统中最基本的部分,可理解成看得见、摸得着的实物。一台电脑是由许多的零部件组成,只有这些零部件组合在一起协调工作,才能称之为电脑。一般计算机的硬件可以简单分为以下部件: 主机&#xff08…

Nginx location匹配优先级 与 Rewrite

目录 前言locationlocation 常用的匹配规则location 优先级实例演示 rewrite前言rewrite跳转实现rewrite 执行顺序语法格式rewrite全局变量实例演示 前言 从功能看 rewrite 和 location 似乎有点像,都能实现跳转,主要区别在于 rewrite 是在同一个域名内…

抛弃传统网络?SDN协议、标准、接口对比分析

随着网络规模的不断扩大和复杂性的增加,传统的网络架构已经难以满足日益增长的网络需求。SDN(Software Defined Networking)技术的出现,为网络的管理和控制带来了革命性的变化。SDN的核心思想是将网络的控制和管理从传统的分散式硬…

STL-string-2

Iterators Capacity resize void resize (size_t n);void resize (size_t n, char c); Resize string 将字符串的大小调整为n个字符的长度。 如果n小于当前字符串长度,则当前值将缩短为其第一个n字符,删除第n个字符之后的字符。 如果n大于当前字符串长…

Python接口自动化之yaml配置文件

Python自动化测试:7天练完这60个实战项目,年薪过35w。 软件测试技术分享总结 在自动化过程中,需要使用配置文件储存数据,比如数据库信息、账号信息、域名等。 其中,yaml文件是一种配置文件类型,相比较in…

职场已是00后的天下了,起薪20k,想都不敢想

2023年很卷吗?不,只能说你还得学! 都说00后已经躺平了,但是有一说一,该卷的还是卷! 这不,前段时间我们公司新招来了一个00后小伙,工作都没2年,跳槽到我们公司就起薪20K&…