高并发压测的场景

40岁老架构师尼恩的读者社群(50+)中,很多小伙伴拿不到offer,或者拿不到好的offer

尼恩经常给大家 优化项目,优化简历,挖掘技术亮点。

在指导简历的过程中, Java 调优是一项很重要的指导。

问题是,很多小伙伴,连一点调优的基础都没有, 当然,连高并发的场景也搞不清楚。

实际上,无论是调优,还是高并发的场景,我们都需要解决一些基础问题,比如说:

一亿用户量,平均每人每天10次的业务量,要求并发数在5000以上,峰值在5w到10w之间,QPS在25w以上, 如何进行压测?如何进行调优?

对于架构师、高级开发来说, 调优是 核心内容, 那么压测更是内功中的内功。

尼恩团队从 高并发压测实操开始,给大家梳理一个系列的**《Java 调优圣经》PDF** 电子书,包括本文在内规划的四个部分:

(1) 调优圣经1:零基础精通 Jmeter 分布式压测,10Wqps+压测实操 (基本完稿,有点扫尾的工作)

(2) 调优圣经2:零基础精通 JVM 调优实操,实现JVM自由 (写作中)

(3) 调优圣经3:零基础精通 Mysql 调优实操,实现Mysql调优自由 (写作中)

(4) 调优圣经4:零基础精通 Linux、Tomcat 调优实操,实现基础设施调优自由 (写作中)

以上的多篇文章,后续将陆续在 技术自由圈 公众号发布。 完整的《Java 调优圣经》PDF,可以在文末【技术自由圈】公众号 找尼恩获取。

本书目录

文章目录

性能测试基础

本文从性能测试0基础开始,为大家介绍一下10Wqps+压测实操。

性能测试是一个开发工程师/架构师必会的技能之一。只有学会性能测试,才能根据得到的测试报告进行分析,找到系统性能的瓶颈所在,而这也是Java调优的中重要的依据。

1、什么是性能测试?

性能测试就是通过特定的方式对被测试系统按照一定测试策略施加压力,获取该系统的响应时间、TPS、吞吐量、资源利用率等性能指标,来检测系统上线后能否满足用户需求的过程。

2、性能测试的重要性

性能测试是检验我们系统性能的重要步骤,只有经过性能测试,得到对应的测试报告,才能根据报告中所呈现的现象(成功率、响应时长、TPS等)来进行分析,找出系统的瓶颈所在,优化系统的性能。

3、性能指标——QPS和TPS

QPS和TPS都是衡量一个系统性能的重要指标之一。

①QPS

QPS,全名 Queries Per Second,意思是“每秒查询率”,是一台服务器每秒能够响应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。

②TPS

TPS 即 Transactions Per Second的缩写,每秒处理的事务数目。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。
客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数,最终利用这些信息作出的评估分。

Qps 基本类似于 Tps,但是不同的是,对于一个页面的一次访问,形成一个 Tps;但一次页面请求,可能产生多次对服务器的请求,服务器对这些请求,就可计入“Qps”之中。

压测的时机

压测的时机很重要,如果时间选择不对,可能会做无用功,简单总结下5个常见的压测场景:

1、上线前压测

常规操作是在上线前,对系统进行一个摸高压测,根据预估的流量,对系统配置进行优化调整,保证运行期间,系统能正常运行。

2、项目上线稳定后,对系统评估

系统上线后,随着用户量不断增加,承受的压力会越来越大,为了让系统在未来的时间内稳定运行,需要通过压测对系统进行评估,以调整配置或优化接口,来充分应对不断增长的用户量。

3、项目研发后期,对系统的检验

在项目后期,由于领导或团队的要求,需要对系统的稳定性做校验,保证系统短时间内流量陡增时能稳定运行,可以给系统的部署提供参考。

4、线上出现性能问题

有些项目为了抢占市场,节省时间,完成了基本的功能就上线了,没有做压测,当用户突然增加出现线上性能问题后,反过来做压测,这种情况的风险是很大的,不推荐。

5、合作方要求

有些合作方对性能有明确的要求,并且写进了合同,这种情况下就必须去做压测了。

压测工具介绍

JMeter

JMeter是Apache公司基于java开发的一款开源压力测试工具,不仅体积小功能全,而且使用起来也非常方便和简单。它是主要用于web应用程序的负载测试,同时它还支持单元测试和有限的功能测试。

JMeter工具的特性有很多,比如动态报告、可移植性、强大的测试IDE等,并且支持不同类型的应用程序、协议、shell脚本、Java对象和jmeter操作数据库等等。

Jmeter工具的优点 :

开源免费,安装过程比较简单

Jmeter工具的应用范围比较广

C/S架构,基于jJmeter工具有着丰富的逻辑控制器,且具备强大的监控组件

ava实现的工具,配置起来比较容易,更偏向于性能测试

JMeter提供了BeanShell编程能力,可以编写出比较灵活的测试脚本

JMeter提供了比较高级的扩展能力,允许自己定义和扩展新的协议支持

JMeter的社区相对完善,可以提供丰富的协议支持

SoapUI

SoapUI是一个开源测试工具,主要通过soap/http来检查、调用、实现Web Service的功能/负载/符合性测试。

SoapUI非常流行的用于SOAP和REST的开源API测试自动化框架,同时还支持功能测试、性能测试、数据驱动测试和测试报告等。

SoapUI工具的优点:

SoapUI工具不需要开发人员编程就可以实现测试用例,可以通过WSDL自动产生测试消

SoapUI工具能够直接引用外部属性文件来简化测试步骤

SoapUI支持REST和SOAP服务

使用来自文件和数据库的数据进行强大的数据驱动测试

SoapUI提供方便的接口能够集成JBoss、Ant、XMLBean、ApacheTCPMon等多种工具

使用RESTful模拟服务

SoapUI工具的缺点:

SoapUI使用的是自己的Web服务客户端,导致客户端并不能像真正的Web服务消费者那样去调用Web服务

SoapUI中不能控制Mock服务的WSDL文件服务端点的URL

需要破解

SoapUI不支持JMS协议

Postman

Postman 是一款支持http协议的接口调试与测试工具,其主要特点就是功能强大,使用简单且易用性好 。它不仅可以发送所有类型的HTTP请求 (其中包括GET, POST, PUT, DELETE…等等),且还能附带所有数量的参数和Headers。不仅如此,它还可以提供测试数据和环境配置数据的导入导出,对于付费的Post Cloud用户还可以创建属于自己的 Team Library团队协作式测试,并能将自己的测试收藏夹和用例数据和整个团队共享。

Postman工具的优势

跨平台

门槛比较低且上手快

自带各种代码模块

图形界面非常清晰

免费版的功能就已经非常强大了,支持http,https协议

支持抓包,保存历史记录,多终端同步用例

结合界面操作可以快速的配置接口请求信息,提供各种类型接口配置,以及数据配置

有丰富响应断言,方便用于接口进行快速验证

Postman工具的缺点:

无法连接数据库

不能操作文件相关的操作,无法读写数据库,不能使用非HTTP协议

不支持通过url搜索用例且不能指定执行失败的测试用例

Selenium

Selenium是网页应用中最流行的开源自动化测试框架。由于不断地完善,Selenium工具目前成为很多Web自动化测试人员的选择,特别是那些有高级编程和脚本技能的测试人员。Selenium也成为了其他开源自动化测试工具比如Katalon Studio,Watir,Protractor和Robot Framework等的核心框架。

Selenium 支持多系统环境(Windows,Mac,Linux)以及多种浏览器(Chrome,FireFox,IE以及无头浏览器(没有界面))。它的脚本可以由各种不同的编程语言编写,比如 Java,Groovy、Python,C+,PHP,Ruby 以及 Perl等。

Selenium工具的优势 :

界面可视化,对于初学者来说比较容易上手。

不深入理解动态加载和后端的交互也可以进行数据采集

比较符合普通人操作网页进行复制粘贴的习惯

Selenium工具的劣势势 :

加载速度比较慢,容易造成阻塞,导致采集效率不高

比较不易迁移,要适配没有界面的linux且需要进行多次修改

LoadRunner

LoadRunner,是一款商用性能测试工具,可以用于预测系统行为和性能的负载测试。LoadRunner能够对整个企业架构进行测试。

企业使用LoadRunner能最大程度的减少测试时间,优化性能和加速应用系统的发布周期。LoadRunner可适用于各种体系架构的自动负载测试,能预测系统行为并评估系统性能。

LoadRunner工具的优势 :

运行比较稳定

监控指标比较齐全

对于性能测试的结果很细致

可以模拟成千上万的用户实施并发负载及实时性能监测的方式来确认和查找问题

LoadRunner工具的劣势 :

属于收费工具,且价格比较贵(所以一般企业会购买)

安装程序繁杂,操作比较难

为什么选择JMeter

JMeter 可以用于对服务器、网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析整体性能。另外,JMeter 能够对应用程序做功能/回归测试,通过创建带有断言的脚本来验证你的程序返回了你期望的结果。为了最大限度的灵活性,JMeter 允许使用正则表达式创建断言。

Apache jmeter 可以用于对静态的和动态的资源(文件,Servlet,Perl 脚本,java 对象,数据库和查询,FTP 服务器等等)的性能进行测试。它可以用于对服务器、网络或对象模拟繁重的负载来测试它们的强度或分析不同压力类型下的整体性能。你可以使用它做性能的图形分析或在大并发负载测试你的服务器/脚本/对象。

JMeter 的特色

  1. 开源许可:Jmeter 是完全免费的,并提供了源码可供自定义开发
  2. 图形界面模式:提供了方便的图形界面来编辑和开发测试脚本
  3. 平台无关:可以轻易在 windows、linux、mac 上运行
  4. 多线程框架:通过线程组,能够轻易的设置不同测试的并发用户
  5. 图形测试结果:提供了图表、表格、树、文件等格式的结果显示
  6. 易于安装:jmeter 不需要安装,下载解压即可用
  7. 高扩展性:jmeter 支持用户自定义测试脚本,同样还提供了各种插件
  8. 多测试类型支持:支持性能测试、分布式测试、功能测试
  9. 仿真模拟:支持多用户并发测试
  10. 多协议支持:支持 http、jdbc、ldap、soap、jms、ftp 等等协议
  11. 录制&回放:支持用 badboy 或 jmeter 录制,不过笔者从来不用该模式,纯手工最佳
  12. 脚本测试:jmeter 支持 beanshell 和 selenium

Jmeter主要元件

  1. 测试计划:是使用 JMeter 进行测试的起点,它是其它 JMeter测试元件的容器。
  2. 线程组:代表一定数量的用户,它可以用来模拟用户并发发送请求。实际的请求内容在Sampler中定义,它被线程组包含。
  3. 配置元件:维护Sampler需要的配置信息,并根据实际的需要修改请求的内容。
  4. 前置处理器:负责在请求之前工作,常用来修改请求的设置。
  5. 定时器:负责定义请求之间的延迟间隔。
  6. 取样器(Sampler):是性能测试中向服务器发送请求,记录响应信息、响应时间的最小单元,如:HTTP Request Sampler、FTP Request Sample、TCP Request Sample、JDBC Request Sampler等,每一种不同类型的sampler 可以根据设置的参数向服务器发出不同类型的请求。
  7. 后置处理器:负责在请求之后工作,常用获取返回的值。
  8. 断言:用来判断请求响应的结果是否如用户所期望的。
  9. 监听器:负责收集测试结果,同时确定结果显示的方式。
  10. 逻辑控制器:可以自定义JMeter发送请求的行为逻辑,它与Sampler结合使用可以模拟复杂的请求序列。

1、测试计划(Test Plan)

用来描述一个性能/接口测试脚本和场景设计,包含与本次测试所有相关的功能。

也就是说,使用JMeter进行测试的所有内容,都是于基于一个测试计划中。

在换个说法,一个测试计划就对应一个JMeter测试脚本。

JMeter-GUI中,只能编辑一个测试计划,如果需要新创建一个测试计划,就要开启一个新的JMeter-GUI窗口界面。

2、线程组<Threads(Users)>

线程组元件是任何一个测试流程的起始点,在一个测试计划中的所有元件都必须在某个线程组下。

线程组概括说明

  1. 线程组是一个测试流程的起始点。
  2. 线程组中可以有多个线程。线程组也可以看作是一个虚拟用户组,线程组中的每一个线程都可以理解为相当于一个“虚拟用户”。
  3. 线程组中一个取样器代表一个请求,一个请求等同于一个线程。
  4. 每个线程都会独立的运行测试计划,互不干扰,多个线程用于模仿对服务器的并发访问。
  5. 线程组元件可以设置线程数、设置执行测试的次数等操作。

3、取样器(sampler)

取样器是用来模拟用户操作的,向服务器发送请求以及接收服务器的响应数据。

取样器是线程组内部的元件,也就是说取样器只能在线程组中添加。

取样器(Sampler)是性能测试中向服务器发送请求,记录响应信息,记录响应时间的最小单元。(取样器通常要进行这三个工作)

取样器是按照测试计划树的顺序从上到下执行的。且取样器配合控制器使用,可以修改取样器的执行顺序和次数。

4、逻辑控制器(Logic Controller)

我们有编程基础的人都知道,提到逻辑主要就是条件和循环。

JMeter官网对逻辑控制器的解释是:Logic Controllers determine the order in which Samplers are processed.

意思是说,逻辑控制器可以控制采样器(samplers)的执行顺序

由此可知,控制器需要和采样器一起使用,否则控制器就没有什么意义了。放在控制器下面的所有的采样器都会当做一个整体,执行时也会一起被执行。

JMeter提供了17种逻辑控制器,它们各个功能都不尽相同,大致可分为2种类型:

  • 一类是用于控制 test plan (测试计划)中 sampler (取样器)节点发送请求的逻辑顺序的控制器,常用的有If Controllerswitch ControllerRuntime ControllerLoop Controller(循环控制器)等。
  • 另一类是用来组织可控制的sampler 节点,也就是对测试计划中的取样器进行分组,方便JMeter统计执行结果,以及运行脚本时的控制操作等。 如Transaction Controller(事务控制器)、Throughput Controller(吞吐量控制器)等。

5、配置元件(Config Element)

JMeter的配置元件(config element)用于提供对静态数据的配置支持,可以为取样器设置默认值和变量。

配置元件有很多的功能,读取文件数据,设置公共请求参数,赋予变量值等,以便后续取样器使用。

(类似于项目中配置文件的作用,如数据、地址、数据库链接等进行配置)

例如:性能测试中为了模拟大量用户操作我们往往需要做参数化, JMeter的参数化可以通过配置元件来完成,利用CSV Data Set config(CSV数据文件设置)可以将本地数据文件形成数据池 (Data Pool),它可以帮助我们从文件中读取测试数据。

另外JMeter也提供了众多的函数来帮我们生成动态数据。(通过函数助手可以查看到,后续会讲到)

再例如,配置元件还可以用来记录服务器的返回数据,如HTTP Cookie Manager 可以用于对 HTTP Request Samplercookie 进行管理。

简而言之,配置元件是为取样器提供预备数据,然后由取样器发出请求。

6、定时器(Timer)

用户实际操作时,并非是连续点击,而是存在很多停顿的情况,例如:用户需要时间阅读文字内容、填表、或者查找需要点击的链接等。为了模拟用户实际情况,在性能测试中我们需要考虑操作时间。若不认真考虑操作时间很可能会导致测试结果的失真。例如,估计的可支撑用户数可能会偏小。

在性能测试中,访问请求之间的停顿时间被称之为思考时间

那么如何模拟这种停顿呢?我们可以借助JMeter的定时器元件实现。

JMeter中的定时器一般被我们用来设置延迟与同步(操作之间的等待时间)。定时器的执行优先级高于Sampler(取样器),在同一作用域(例如控制器下)下有多个定时器存在时,每一个定时器都会执行,如果想让某一定时器仅对某一Sampler有效,则可以把定时器加在此Sampler节点下。

7、前置处理器(Per Processors)

前置处理器是在取样器发出请求之前执行一些操作。即:如果将前置处理器附加到取样器元件,则它将在该取样器元件运行之前执行。

前置处理器主要是用来处理,请求在实际发送之前的一些准备工作,比如取样器参数设置、环境变量设置、脚本预处理等操作。

例如:当URL中有sessionID一类的session信息时,可以通过该处理器填充发出请求实际的sessionID。

8、后置处理器(Post Processors)

用于对Sampler发出请求后得到的服务器响应进行处理。一般用来提取响应中的特定数据(类似LoadRunner中的关联)。

例如:我们在做接口测试的时候,难免会遇到一个接口的请求参数是另一个接口的响应结果,这个时候就需要用到后置处理器来处理我们的请求参数。如系统登录成功后我们要获取sessionid,在后面业务操作中服务器会验证这个sessionID,获取sessionID这个过程,就是用后置处理器中的正则表达式提取器来完成。

后置处理器常用于:处理响应数据,提取某个值。

9、断言(Assertions)

断言是自动化测试中最重要且绕不开的一个概念,让自己的程序尽可能像人一样去做判断,这是自动化测试需要实现的重要功能。

JMeter中的断言用于检查测试中得到的响应数据等是否符合预期,Assertions一般用来设置检查点,用以保证性能测试过程中的数据交互与预期一致。(它的作用和LoadRunner中的检查点类似)

JMeter中断言的原理:在Request的返回层面,增加一层判断机制,因为Request成功了,并不代表结果一定正确。

一个Sampler可以添加多个断言,根据你的检查需求来添加相应的断言,多个断言属于并的操作。当Sampler下所有的断言都通过了,那么才算是请求成功。

10、监听器(Listener)

JMeter中的监听器,是对测试结果进行处理和可视化展示的一系列组件,能够显示取样器请求和响应的细节以及请求结果,包括消息头,请求的数据,响应的数据。

常用的监听器有图形结果、查看结果树、聚合报告等。

注意

  1. 监听器放的位置不同,查看的结果也不同。
    在线程组下添加监听器,查看线程组下所有请求的结果;
    放在具体某个请求下,只查看此请求的结果;
    若放在某个控制器节点下,则查看此控制器下节点执行的结果;
  2. 该监听器推荐做调试用,在实际运行压测时,应该禁用。因为大量请求时,启用监听器时打印的日志比较多,会造成大IO消耗,影响压力机性能。
  3. 不同的监听器,通过不同的方式,展示服务器响应信息,但是它们原始结果数据都是一样的。
  4. JMeter监听器有两种方式存储监听记录:
    1)默认保存方式:CSV格式。占用磁盘比较少,推荐使用这种方式保存。
    2)xml保存方式:保存数据最全面,但是占用内存大。

准备工作Jmeter安装

运行Jmeter要先安装JDK,安装JDK1.8以上版本,JDK的安装这里就不多说了

jmeter官网下载地址:https://jmeter.apache.org/download_jmeter.cgi

下载解压后,在在bin路径下双击jmeter.bat运行jmeter

JMeter汉化以及更改界面背景

启动Jmeter找到 options 》choose language 》chinese(简体繁体自己选)。
但是设置完重新启动后还会变为默认英文。

永久默认汉化

在Jmeter的安装目录下的bin目录中找到 jmeter.properties这个文件,用文本编辑器打开。

添加language=zh_CN 即可实现永久型汉化。

内存配置

当并发数量过多时,JMeter内存配置不满足此时并发需求,会导致请求出现异常使结果不正确。Windows下右键编辑jmeter/bin/jmeter.bat,修改以下配置即可:

# 修改Xmx的值来增大JMeter内存配置
set HEAP=-Xms1g -Xmx2g

整体分3部分:

  1. 菜单栏
  2. 工具栏
  3. 操作界面(左:标签 右:标签信息)

  1. 常用组件介绍

一个完整的测试计划分为3部分:全局设置、测试主体和测试结果

Jmeter使用介绍

使用jmeter 添加接口请求

增加线程组

在添加接口请求之前需要先添加线程组,用来管理所有接口请求,一般一个功能模块为一个线程组

增加HTTP请求

添加好线程组后,右键点击线程组添加取样器中的HTTP请求,HTTP请求中可以配置接口的访问信息

在HTTP请求中配置接口的访问信息

配置好接口的访问参数后,可以点击jmeter中的运行按钮,在运行之前需要先保存脚本,根据提示设置脚本保存的目录

增加察看结果树

保存完脚本后,发现无法查看接口运行的情况,需要在线程组中添加监听器中的察看结果树

在查看结果数中,可以查看接口返回数据的情况,点击查看结果数中接口的名称,可以查看单条接口的请求,响应数据等信息

定位察看结果树中的报错情况

如果是绿色状态,代表jmeter与接口服务器通信正常,错误原因应该为参数值设置错误,如果是红色报错,则证明jmeter与接口服务器之间通信异常,应为接口连接的问题

Jmeter 单机压测过程

可做压测的工具很多,业界用得比较多的是Jmeter,今天我们就以Jmeter为例,分享下做压测的6个步骤:

1、编写压测脚本

1)线程中添加HTTP信息头管理器

线程组右键–>添加–>配置元件–>HTTP信息头管理器

  1. 点击下方 Add (添加)
  2. Name (名称)中输入 Content-Type
  3. Value (值)中输入 application/json

2)线程组中添加HTTP请求默认值

添加HTTP请求

3)添加响应断言

响应断言的作用在于可以自动判断接口返回数据是否符合预期,通过对比接口返回数据中的固定字符串,实现判断的目的

由于响应断言是判断接口返回的数据,所以需要添加到接口中而不是线程组中

在响应断言面板中配置响应断言相关的信息

要测试的字段:由于断言用来判断接口返回数据,所以判断的主体为响应文本

模式匹配规则:“包括”的意思为接口响应数据中包括预期的字段

“匹配”与“equals”的意思都是接口响应数据与预期字段相等

“Substring”的意思为子字符串

“否”代表在选择的条件上加否,比如选择包括+否,意思为不包括

要测试的模式:预期字段

如上:返回的响应数据中包括code字符串,判断接口响应数据是否符合预期

当接口返回数据与响应断言中的不一致时,响应断言会作出相应提示

4)添加断言持续时间

HTTP请求右键–>添加–>断言–>断言持续时间

5)常数吞吐量定时器

线程组上右键 --> 添加–> 定时器 --> 常数吞吐量定时器(Constant Throughput Timer)

6)查看结果树

线程组上右键 --> 添加 --> 监听器 --> 查看结果树

7)聚合报告

线程组上右键 --> 添加 --> 监听器 --> 聚合报告

2、准备压测服务器(测试服务器/线上服务器)

有些项目需要在测试服务器上进行,而有些则直接在线上服务器进行,例如还未上线的活动类项目,就可直接在线上压测,不同的服务器配置,压出来的结果是不同的。

3、开始压测

提前与开发和产品同学确认并发量,如果项目有明确的用户数,比如500用户,那就直接用500并发或者稍稍高于500的并发,如果项目没有明确的并发,可根据当前项目情况酌情施压。

在压测过程中,注意观察服务器资源消耗情况,例如cpu,内存,磁盘,网络等以及服务器日志。

观察服务器的压力,如果在测试环境,可以在服务器上装个nmon工具,可实时查看服务器的资源消耗情况,如果是线上环境,一般不能直接远程服务器,可以找运维同学要链接,比如这次运维同学直接给链接地址,登录可直接查看服务器的资源消耗情况。

主要是看是否有报错信息以及请求是否打到了测试服务器上。

4、记录结果

主要包括服务器配置,压测场景、Jmeter聚合报告以及接口报错情况,服务器资源监控等。

1)服务器配置

测试环境机器配置:单台机器,配置为4核6G内存

订单保存接口

2)聚合报告

1s起1000个线程数,循环次数1次,查看时间段内的资源消耗情况图

主要关注平均响应时间Average,Error%,Throughput

3)测试结果

查看结果树,将报错的类型全部列举出来,例如存在连接超时的报错:Connection timed out

4)资源监控

关注CPU使用率,内存使用率,网络流量

5、提性能Bug和验证Bug

如果有的接口有性能Bug,提Bug给开发,开发修复后,再次压测,进行回归测试,验证Bug已修复。

6、发送压测报告

将步骤4的结果进行简单的文字分析总结,发送压测报告

Jmeter 分布式压测

一亿用户量,平均每人每天10次的业务量,要求并发数在5000以上,峰值在5w到10w之间,QPS在25w以上

什么是分布式测试

回到这个压测场景:

一亿用户量,平均每人每天10次的业务量,要求并发数在5000以上,峰值在5w到10w之间,QPS在25w以上

这种测试,用单个实例是无法完成的。

需要使用分布式压测。

分布式测试是指通过局域网和Internet,把分布于不同地点、独立完成特定功能的测试计算机连接起来,以达到测试资源共享、分散操作、集中管理、协同工作、负载均衡、测试过程监控等目的的计算机网络测试。

为什么要使用分布式压力测试

普通压力测试一般是采用单台机器对目标服务器产生的压力,因为受限于CPU、内存、网络、IO等因素的影响,通常只能模拟几十到几百用户的并发访问。分布式压测是利用多台机器同时向目标服务器产生压力,可以模拟几万到上亿级别用户的并发访问。

尼恩用自己的 分布式Netty 压测工具, 完成了最高 17w qps 的超高吞吐量测试

但是 尼恩分布式Netty 自研的分布式压测工具,非常的简陋。

所以, 更好的方式为,使用 分布式jmeter 完成 超高并发压测。

Jmeter分布式压测前的准备工作

(1)确保master和各个slave上使用相同版本的JMeter 和 Java。混合版本将无法正常工作。
(2)master和各个slave的防火墙已关闭或打开了正确的端口,且端口未被占用。

(3)master和各个slave上安装的杀毒软件已关闭。

(4)master和各个slave在同一个子网内,尽量减少网络带宽的影响,减少时延问题。如果是多网卡环境需要保证启动的网卡都在同一个网段。

(5)确保 JMeter 可以访问服务器,可以使用ping命令查看。

(6)已经为 RMI 设置了 SSL或禁用了它。

(7)master和各个slave上安装Jmeter全部启动成功。

Docker 进行Jmeter 分布压力测试

一个 JMeter实例将能够控制多个远程 JMeter 实例对应用程序进行更大的负载测试。 JMeter 使用 Java RMI [远程方法调用] 与分布式网络中的对象进行交互。

DockerJMeter分布式测试中扮演的角色

进行分布式负载测试就需要1个master,N个slave来生成大量的负载。每个JMeter slave都需要安装相同(指定)版本的JavaJMeter

应该打开指定的端口并运行JMeter服务器,准备就绪并等待主服务器发送指令。

手动设置三五台计算机看起来很容易,那如果我们必须对50/100/1000台计算机执行此操作呢?还可以想象如果将来需要在所有机器上升级JMeter版本或者Java版本会发生什么?可以想象工作量得有多大,至此,Docker就该派上用场了。

如何做

  • 通常,我们会在名为 Dockerfile 的文件中配置JMeter分布式测试的整个基础架构,检查dockerfile并阅读注释以了解每个步骤的作用,最后生成包含JMeterjava等工具集合的镜像。
  • 然后,再根据生成的基础镜像,开始部署master机器及slave机器。
  • 接着,在master机器执行压测命令。
基础镜像Dockerfile

在分布式压测中,所有的环境都应该使用相同版本的Java、JMeter、plugins等。master和slave之间唯一区别是所公开的端口和正在运行的进程。因此,让我们创建一个Dockerfile,该文件具有master和slave的所有通用步骤,称其为 jmbase 基础镜像,我们将需要执行以下操作来构建基本映像:

  • 需要Java8 –因此,让openjdk-8-jre slim版本,大小保持尽可能小。
  • 需要安装公共的工具包,例如wget、net-tools、telnet、vim等。
  • 需要最新版本的JMeter,为版本创建变量,以便后续维护。
  • 安装需要的插件。
  • 添加一个包含测试用例的文件夹。

Dockerfile文件,作用是生成基础镜像

FROM openjdk:8-jre-slim

##jmeter版本
ARG JMETER_VERSION=5.5

#安装jmeter
RUN mkdir /jmeter \
	&& cd /jmeter/ \
#	国内镜像高速下载jmeter
	&& wget https://mirrors.aliyun.com/apache/jmeter/binaries/apache-jmeter-$JMETER_VERSION.tgz \
#	官方下载jmeter
#	&& wget https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-$JMETER_VERSION.tgz \
	&& tar -xzf apache-jmeter-$JMETER_VERSION.tgz \
	&& rm apache-jmeter-$JMETER_VERSION.tgz

#JMETER_HOME环境变量
ENV JMETER_HOME /jmeter/apache-jmeter-$JMETER_VERSION/
ENV PATH $JMETER_HOME/bin:$PATH

WORKDIR $JMETER_HOME

#脚本复制到当前路径
COPY ./scripts/user.properties bin/user.properties
COPY ./scripts/entrypoint.sh ./bin

RUN chmod +x  ./bin/entrypoint.sh


EXPOSE 60000 1099 50000
ENTRYPOINT ["entrypoint.sh"]

entrypoint.sh脚本

这是entrypoint.sh脚本,在容器生成时,根据容器启动时的命令,输入master或者server,选择打开对应的端口号。jmeter-server运行的时候公开端口1099和50000。

#!/bin/bash
set -e

echo "Starting entrypoint!"
pwd
case $1 in
    master)
        tail -f /dev/null # 防止容器启动后退出
        ;;
    server)
        $JMETER_HOME/bin/jmeter-server \
            -Dserver.rmi.localport=50000 \
            -Dserver_port=1099
        ;;
    *)
        echo "Sorry, this option doesn't exist!"
        ;;
esac

exec "$@"

user.properties配置文件

在容器生成时,安装好jmeter后,把jmeteruser.properties配置文件替换一下。

#将注释打开,并且将值修改成true,就会打开该条记录,JMeter就会将该条信息输出到我们指定的.jtl文件中。
jmeter.save.saveservice.default_delimiter=\t
jmeter.save.saveservice.print_field_names=true

#关闭SSL传输
server.rmi.ssl.disable=true
镜像生成

生成基础镜像jmeterbase:v1,命令如下:

docker build -t jmeterbase:v1 . 
启动容器docker-compose

这是docker-compose.yml文件,基础镜像jmeterbase:v1生成后,使用docker-compose命令启动容器,并执行负载均衡。

version: '3'
services:
  master:
    image: jmeterbase:v1
    command: master
    container_name: jmeter-master # 容器名称
    tty: true
    ports:
      - "60000"
    volumes:
      - "../sample_test/:/jmeter/sample_test/"
    networks:
      - jmeter-network

  server:
    image: jmeterbase:v1
    command: server
    container_name: jmeter-slave # 容器名称
    tty: true
    ports:
      - "50000"
      - "1099"
    networks:
      - jmeter-network
    depends_on:
      - master

networks:
  jmeter-network:
    driver: bridge

注意:volumes挂载的目录,此压测脚本是在当前目录,或者上级目录。

使用docker-compose命令启动容器,并后台执行。

docker-compose up -d
两个镜像的区别

jmeter-maste与jmeter-slave使用相同的镜像,区别是启动命令不同。

  • slave:启动jmeter-server进程,并开启远程端口
  • master:通过-R将任务分配至所有slave节点。
执行压测

进入容器

docker exec -it jmeter-master /bin/sh 

执行压测脚本

jmeter -n -t ../sample/baidu.jmx -l ../sample/data/baidu.jtl -j ../sample/data/baidu.log -R 172.18.0.3,172.18.0.4

若脚本没有挂载到容器,也可以将本地jmeter脚本复制到容器中,命令如下:

docker exec -i master sh -c 'cat > /jmeter/apache-jmeter-5.5/bin/baidu.jmx' < baidu.jmx
查看结果

报表文件在脚本文件test.jmx同一目录下

10Wqps的压测实操过程

使用上面的 分布式实操的环节,请容易的压测到 1Wqps以上。

那么,如果是 10Wqps呢? 其实很简单, 进行docker 实例扩容就可以了。

比如,需要扩容到15个实例,命令如下

docker-compose scale slave=15

具体的实操环境比较复杂,而且需要多次实验,反复实验和扩容。

10Wqps 实操的过程,留个彩蛋 后续 PDF 中给大家揭秘。 尼恩团队的所有文章和PDF电子书,都是 持续迭代的模式, 最新版本永远是最全的。

《Java 调优圣经》迭代计划

尼恩团队从 高并发压测实操开始,给大家梳理一个系列的《Java 调优圣经》PDF电子书,包括本文在内,规划的四个部分:

(1) 调优圣经1:零基础精通 Jmeter 分布式压测,10Wqps+压测实操 (基本完稿,有点扫尾的工作)

(2) 调优圣经2:零基础精通 JVM 调优实操,实现JVM自由 (写作中)

(3) 调优圣经3:零基础精通 Mysql 调优实操,实现Mysql调优自由 (写作中)

(4) 调优圣经4:零基础精通 Linux、Tomcat 调优实操,实现基础设施调优自由 (写作中)

以上的多篇文章,后续将陆续在 技术自由圈 公众号发布。 完整的《Java 调优圣经》PDF,可以在文末【技术自由圈】公众号 找尼恩获取。

技术自由的实现路径 PDF:

实现你的 架构自由:

吃透8图1模板,人人可以做架构

10Wqps评论中台,如何架构?B站是这么做的!!!

阿里二面:千万级、亿级数据,如何性能优化? 教科书级 答案来了

峰值21WQps、亿级DAU,小游戏《羊了个羊》是怎么架构的?

100亿级订单怎么调度,来一个大厂的极品方案

2个大厂 100亿级 超大流量 红包 架构方案

… 更多架构文章,正在添加中

实现你的 响应式 自由:

响应式圣经:10W字,实现Spring响应式编程自由

这是老版本 《Flux、Mono、Reactor 实战(史上最全)

实现你的 spring cloud 自由:

Spring cloud Alibaba 学习圣经

分库分表 Sharding-JDBC 底层原理、核心实战(史上最全)

一文搞定:SpringBoot、SLF4j、Log4j、Logback、Netty之间混乱关系(史上最全)

实现你的 linux 自由:

Linux命令大全:2W多字,一次实现Linux自由

实现你的 网络 自由:

TCP协议详解 (史上最全)

网络三张表:ARP表, MAC表, 路由表,实现你的网络自由!!

实现你的 分布式锁 自由:

Redis分布式锁(图解 - 秒懂 - 史上最全)

Zookeeper 分布式锁 - 图解 - 秒懂

实现你的 王者组件 自由:

队列之王: Disruptor 原理、架构、源码 一文穿透

缓存之王:Caffeine 源码、架构、原理(史上最全,10W字 超级长文)

缓存之王:Caffeine 的使用(史上最全)

Java Agent 探针、字节码增强 ByteBuddy(史上最全)

实现你的 面试题 自由:

4000页《尼恩Java面试宝典 》 40个专题

以上尼恩 架构笔记、面试题 的PDF文件更新,▼请到下面【技术自由圈】公号取 ▼

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐