`
iamlotus
  • 浏览: 108064 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

一次压力测试的故事

阅读更多

最近作了个系统,面向普通网民,设计的吞吐率是单机>1万/s,可水平扩展。我之前作的系统多是面向商业用户,很少有这么高的吞吐率要求,所以这次设计过程中对并发,资源竞争啥的也格外注意,这些暂且不表。等到开发完成,开始压力测试的时候,遇到了些故事,颇花了一些时间,此过程中也学到了不少知识。

 

系统开发完成时,运行在jetty上。当时QA作了一次压测,用5台肉鸡压一个server,得出结论是达到要求,当时我也觉得这就OK了。由于jetty用的是NIO,按照网上的说法,对大量短连接的应用,tomcat的BIO可能更适合,所以我想试试两者的差异。因为QA暂时没有时间配合,我只能自己开始鼓捣,而这一鼓捣就开始有故事了。

 

QA用jmeter作压力测试,我没用过jmeter又懒得从头学,就自己写了个肉鸡客户端,多线程以socket方式向服务器发请求,考虑到客户端本身不是重点,肉鸡就用socket直接写了:每个线程反复执行建立socket->发送->接收->关闭的过程,跑一段时间后统计下成功和各种异常的数目。

第一阶段测试的重点是BIO和NIO的差异,而不是HTTP栈的解析效率,所以直接码了个简单的多线程Socket服务器,ServerSocket.accept()一个Socket传给线程池,线程里的线程对这个socket跑接收->发送->关闭的过程。 SocketServer写好后用两个肉鸡就压上了,然后问题就来了。

肉鸡开始很快,但是一段时间后就几乎hang在那里不动,开始出现异常,包括 connection reset by peer或者connection timeout,过一会儿后吞吐量能上去一点,但很快又落下来,如此反复。这时用jvisualvm看Server,基本就没loading,那是为啥呢?

第一个反应是我的SocketServer写的有问题,于是用NIO手写了个逻辑相同的NioServer,但问题依旧,用mina框架写了个MinaServer再测也还是一样。于是觉得问题不是出现在Server的写法上,而是其它地方。在网上搜了半天,试了不少方法后,觉得可能是http://performtest163.blog.163.com/blog/static/14007696420115295119462 说的问题,看了看跑server的机器

/proc/sys/net/ipv4/tcp_tw_reuse 

/proc/sys/net/ipv4/tcp_tw_recycle 

这两个值确实都没开启,因为测试机不好随便重启,换了个机器找OP要到权限后将这两个值设为1并重启机器后,吞吐量一下子上去了,但客户端还是出现了大量的连接异常,而且这个简单的SocketServer单肉鸡的吞吐率居然比QA测的实际运行在jetty 上的Server低一半还多,这就让人很难理解了。

还是怀疑Server写法的不同。详细分析了代码后,问题应该出现在这里:

重温下以上配套的SocketServer和SocketClient逻辑

Client: 建立socket->发送->接收->关闭

Server: accept socket->接收->发送->关闭

两边都会close socket,那么到底是那边的关闭起作用了?对于这组逻辑,理论上说发送方(Server)应该先到达关闭,但由于tcp是全双工的,发送方也需要等待接收方的SYNC,所以无法确定。不过按照链接中的说法,tcp_tw_reuse 针对的是Server端主动关闭造成的TIME_WAIT,既然打开tcp_tw_reuse起了作用,所以推测这组逻辑中应该是Server端的关闭起了作用。 

另外我又去查了一下,通常HTTP SERVER除非超时,不会主动关闭socket。所以这里的差异可能是由关闭方不同造成的,顺着这个思路,我又用apache HttpClient写了个JettyClient肉鸡去压实际的jetty系统。

这个JettyClient中肉鸡中每个线程的逻辑为反复跑

new HttpClient()->用new 出来的HttpClient发一条Get->接收HttpResponse->关闭HttpClient

结果一会儿工夫肉鸡又Hang住了。由于有了前面的经验,很快发现是由于主动关闭连接,造成肉鸡的Socket耗尽的原因。但问题又来了

1) 肉鸡上确实没有打开tcp_tw_reuse ,肉鸡也不能随便打开这个选项并重启

2) 更关键的是,为什么QA的压力测试用例没有爆出这个问题呢?

 

目前为止,被测系统是同一个,区别只能在QA的测试用例和我的JettyClient中找了。看了QA的测试用例后,我得出的结论是,QA的测试用例写错了。

QA的测试用例中虽然有多线程,但并没有反复的创建和关闭HttpClient,而是在一个线程中初始化时创建了一个HttpClient并反复的通过这个HttpClient去发送Get Request并接受响应。这与线上的实际场景并不一致:线上的100W个请求,可能是100W个浏览器建立了100W个socket各进行一次http通讯,而QA测试的场景是 50个浏览器建立了50个socket,并在每个socket上进行了2W次http通讯。在此过程中,绝大多数socket的建立过程被舍弃了,这就说明了为什么QA的测试用例没有遇到socket耗尽的问题,也说明了为什么我写的简单的SocketServer吞吐量还不如QA给出的指标(这种应用下建立socket的开销可能比逻辑本身开销还要大)。

 

总结一下目前为止的结论:

1) 对于压力很大的Server,最好是打开tcp_tw_reuse,以免Server主动关闭的连接不能及时重用

2) 若要真正模拟线上的情景,还是应该用多台机器,每次都新建并关闭连接。尤其是对于这种逻辑简单的http应用,少量肉鸡大量线程客户端不关闭连接的测试方式远不如大量肉鸡少量客户端连接关闭的方式结果准确

 

<!--EndFragment-->
5
2
分享到:
评论
4 楼 Shen.Yiyang 2014-05-09  
iamlotus 写道
Shen.Yiyang 写道
大量测试机器,每台机器少量短连接,确实更符合实际的HTTP客户端场景。但是对测试服务端的吞吐能力来说,区别不大。吞吐主要有两个方面,针对大量连接的IO,针对大量请求引发的业务处理。对前者,可以加大测试机中的长连接数量,对后者,可以加快测试机中的请求频率。 一定要用短连接做测试的话,本身的操作性是挺差的。
实际上这个系统既有长连接也有短连接。对于长短连接需要不同的测试场景,而对于短连接来说,在后端逻辑非常简单的情况下,单纯通过“加快测试机中的请求频率”得到的吞吐量意义不大啊。

我已经说了,吞吐还包括大量连接情况下的IO。短连接影响的是连接数量,其他方面对服务器的压力没太大差异。
3 楼 iamlotus 2014-05-09  
Shen.Yiyang 写道
大量测试机器,每台机器少量短连接,确实更符合实际的HTTP客户端场景。但是对测试服务端的吞吐能力来说,区别不大。吞吐主要有两个方面,针对大量连接的IO,针对大量请求引发的业务处理。对前者,可以加大测试机中的长连接数量,对后者,可以加快测试机中的请求频率。 一定要用短连接做测试的话,本身的操作性是挺差的。
实际上这个系统既有长连接也有短连接。对于长短连接需要不同的测试场景,而对于短连接来说,在后端逻辑非常简单的情况下,单纯通过“加快测试机中的请求频率”得到的吞吐量意义不大啊。
2 楼 iOracleSun 2014-05-08  
TPS和并发连接数不是同一个概念,从你们的需求来看,QA并没有错,只是将并发连接数设置为50而已。
1 楼 Shen.Yiyang 2014-05-08  
大量测试机器,每台机器少量短连接,确实更符合实际的HTTP客户端场景。但是对测试服务端的吞吐能力来说,区别不大。吞吐主要有两个方面,针对大量连接的IO,针对大量请求引发的业务处理。对前者,可以加大测试机中的长连接数量,对后者,可以加快测试机中的请求频率。 一定要用短连接做测试的话,本身的操作性是挺差的。

相关推荐

    压力测试工具ab

    总结来说,ab工具是一个强大且实用的压力测试工具,对于理解Web服务器性能、进行系统调优以及确保服务在高并发情况下的稳定性具有重要意义。掌握其用法和应用场景,可以帮助IT专业人士更好地维护和优化他们的网络...

    软件压力测试用例格式

    在软件开发过程中,压力测试是不可或缺的一环,它主要用于评估应用程序在高负载或大量并发用户下的性能和稳定性。本文将详细探讨“软件压力测试用例格式”,并提供一个全面的框架来指导压力测试案例的编写。 一、...

    软件测试-web压力测试实验报告

    2. **熟练运用WAS软件进行Web压力测试**:WAS软件是一款强大的压力测试工具,能够生成多线程请求,模拟真实用户的行为,记录和回放测试脚本,以及分析测试结果,为优化Web应用程序提供数据支持。 【实验设备与内容...

    SYN压力测试工具

    **SYN压力测试工具详解** 在网络安全和性能优化领域,SYN压力测试工具扮演着重要的角色。此类工具主要用于模拟大量半打开(SYN)连接,以此来评估服务器或网络设备在面临恶意攻击或高并发流量时的抵御能力。本文将...

    linux tcp服务器压力测试

    在Linux环境中进行TCP服务器压力测试是一项关键的任务,它有助于评估和优化服务器的性能,确保在高并发场景下系统的稳定性和可扩展性。TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输协议,广泛...

    .net 压力测试代码实例

    在.NET开发过程中,压力测试是一项至关重要的任务,它有助于评估应用程序在高负载或并发情况下的性能和稳定性。本文将深入探讨.NET压力测试的概念,并通过一个具体的代码实例来讲解如何进行压力测试。 首先,理解...

    软件测试——web压力测试实验报告

    Web压力测试是软件测试的一个重要环节,主要目的是评估一个Web应用程序在高并发访问下的性能和稳定性。通过模拟大量用户同时访问系统,以检测其在极限条件下的表现,找出可能存在的性能瓶颈,以及系统的崩溃点。本...

    TCP_UDP压力测试工具

    综合以上信息,我们可以推断这个名为“tcpudptest”的压缩包中可能包含一个或多个用于TCP和UDP压力测试的工具。这些工具可能有以下特性: 1. **并发连接模拟**:能创建大量并发socket连接,模拟真实世界的高并发...

    暴风压力测试

    2010年发布的暴风压力测试V7.0版本源码提供了一次深入理解软件性能测试原理和技术的机会。 在进行暴风压力测试时,我们关注的关键知识点包括: 1. **测试目标**:确定要测试的系统或应用,明确测试目标,如响应...

    Apache压力测试工具

    7. **持续测试**:性能测试不是一个一次性的任务,而应随着应用的增长和变化持续进行,确保服务器始终能够应对业务需求。 在提供的文档"abc使用.doc"中,你可能会找到关于如何使用这些工具的详细步骤和个人经验分享...

    负载压力测试及故障

    - **示例一**:在一次压力测试中,发现系统响应时间随并发用户数量的增加而显著变慢。通过分析发现数据库查询效率低是主要原因。解决办法是对SQL语句进行优化,并增加了缓存机制来减轻数据库负担。 - **示例二**:...

    JMeter 压力测试详解PPT

    在软件测试领域,压力测试是一种重要的测试类型,它的主要目的是评估系统在高负载条件下的性能和稳定性。压力测试通常关注的是软件在短时间内处理大量并发用户请求的能力,以确保系统能够有效地应对峰值流量。JMeter...

    ddr窗口压力测试脚本.pdf

    9. 选择测试间隔,例如“1”,可能指的是每秒一次的测试频率。 测试过程中,如果设备出现死机或异常,可以通过复位按键重启设备并继续测试。最终,测试会生成结果,这些结果包括但不限于内存的读写速度、错误率、...

    StressMark压力测试软件

    StressMark测试软件是一个使用Visual C++编写的,开放源代码的测试工具,可以完成服务程序及重要算法的功能和性能测试,其最主要的功能是模拟多线程或多客户端的自动化压力测试。 我们可以利用StressMark软件完成的...

    postjson压力测试.zip

    "postjson压力测试"文件很可能是包含了一系列的测试脚本、测试报告模板或者是一次完整的压力测试案例,对于学习和实践接口压力测试非常有价值。通过分析和学习这些资料,我们可以掌握如何针对POST和GET接口进行有效...

    安卓车机上下电重启压力测试脚本.zip

    2. **测试序列定义**:定义了车机上下电的顺序和频率,比如设定每隔一定时间间隔执行一次重启,或者按照特定的随机模式进行。 3. **错误检测和记录**:在每次上下电过程中,脚本会监控设备的状态,捕获并记录任何...

    SIPp的自动化压力测试

    ### SIPp的自动化压力测试知识点解析 #### 一、系统组成 ##### 1.1 系统的硬件结构 - **组成**: 自动化压力测试系统主要包括三个核心组成部分:**测试管理子系统**、**SIPp测试节点**以及**被测试设备**。 - **连接...

    WebBench_压力测试_webbench_

    3. 长连接:在HTTP协议中,长连接是指在完成一次HTTP请求后不立即关闭TCP连接,而是保持连接开放,以便于进行多次连续的HTTP请求和响应,降低网络开销。 4. 短连接:与长连接相反,短连接是在每次HTTP请求完成后就...

    Web服务器压力测试

    Web服务器压力测试是评估Web服务器能够承受多大负载的重要手段。在这一过程中,通常使用专门的测试工具来模拟多个并发用户访问服务器,以此来确定服务器在面对大量请求时的响应能力和稳定性。标题中提到的ab工具是...

    python+requests接口压力测试500次,查看响应时间的实例

    在这个示例中,我们对www.kuaidi100.com查询接口进行了500次压力测试,查询类型为'zhongtong',postid为'73116039505988'。测试结果显示所有500次请求都成功,平均响应时间约为0.0837秒。 补充知识:在Python中,...

Global site tag (gtag.js) - Google Analytics