简介
- Apache JMeter是Apache组织的开源应用程序软件,是一个纯Java代码编写的桌面级应用程序,常用于压力测试和性能测试,最初版本只是为了web程序而设计,但此后已扩展至其他测试功能
- Apache JMeter可用于测试静态和动态资源,Web动态应用程序的性能。
- 它可用于模拟服务器,服务器组,网络或对象上的繁重负载,以测试其强度或分析不同负载类型下的整体性能。
- 官方文档: https://jmeter.apache.org/index.html
功能
Apache JMeter的功能包括:
- 能够加载许多和性能测试不同的应用程序/服务器/协议类型:
- Web -HTTP,HTTPS(Java,NodeJS,PHP,ASP.NET,…)
- SOAP / REST Web服务
- FTP
- 通过JDBC连接数据库
- LDAP
- 通过JMS的面向消息的中间件(MOM)
- 邮件-SMTP(S),POP3(S)和IMAP(S)
- 本机命令或Shell脚本
- TCP协议
- Java对象
- 功能齐全的Test IDE,可进行快速的Test Plan 记录(来自浏览器或本机应用程序),构建和调试
- **CLI模式(命令行模式(以前称为Non GUI))**可从任何Java兼容的操作系统(Linux,Windows,Mac OSX等)加载测试
- 完整且**随时可以呈现的动态HTML报告**
- 通过从流行的文本格式,HTML,JSON****, **XML或任何文本格式中**提取数据的能力,轻松实现关联
- 完全的可移植性和**100%Java。
- 完整的多线程框架允许通过多个线程进行并发采样,并通过单独的线程组同时对不同的函数进行采样。
- 缓存和脱机分析/重放测试结果。
- 高度可扩展的核心:
- 可插拔采样器允许无限的测试功能。
- 可脚本化的采样器(与Groovy和BeanShell 等JSR223兼容的语言)
- 可以使用可插入计时器选择几个负载统计信息。
- 数据分析和可视化插件可实现出色的可扩展性和个性化。
- 函数可用于为测试提供动态输入或提供数据处理。
- 通过针对Maven,Gradle和Jenkins的第三方开源库,轻松进行持续集成
下载安装以及目录介绍
JMeter安装
JMeter为绿色安装包,可以直接解压后运行,无需进行安装等操作
**注意:**下载的时候需注意JMeter的支持的jdk版本,如我们下载的JMeter5.2的版本,则最低需要JDK8才可以支持
-
打开Apache官方的jmeter下载地址:https://jmeter.apache.org/download_jmeter.cgi
-
下载
zip
安装包
-
解压之后运行bin目录下的
ApacheJMeter.jar
或者jmeter.bat
均可运行JMeter
-
等待运行成功,会出现以下界面
JMeter目录介绍
bin:存放的是JMeter下面的可执行文件
ApacheJMeter.jar:java的运行文件,安装了java运行环境的操作系统均可直接运行此文件启动JMeter
jmeter.bat:Windows的运行文件,也叫批处理文件
jmeter.log:JMeter的日志文件,首次不存在
jmeter.sh:linux系统的运行文件
jmeter:是Mac系统的运行文件
jmeter.properties:系统配置文件
jmeter.server.bat:Windows分布式测试用的服务器配置
jmeter.server:linux分布测试用的服务器配置文件
docs:接口文件档目录
extras:扩展插件目录
lib:所有用到的依赖,里面全部是java的依赖jar包,JMeter运行会自动在lib下寻找所需的jar包并自动引用
licenses:Jmeter的证书目录
printable_docs:Jmeter的用户使用手册
usermanual:有关JMeter的使用说明
JMeter的功能概要
线程组
- setUp线程组
一个特殊类型的线程组,可以用来执行预操作,在测试前进行的一些操作可以使用此线程组,相当于初始化 - tearDown线程组
我们通常使用的线程组,可以看做一个虚拟用户组,线程组中每个线程都可以理解为一个虚拟用户,线程组中包含的线程数量在执行测试过程中是不会发生改变的
配置元件
配置元件用于提供对静态数据配置的支持,如CSV数据文件设置,可以将本地数据文件形成数据池
监听器
用来对测试结果数据进行处理和可视化展示的一系列组件,图形结果、查看结果树、聚合报告等等都是我们经常用到的元件,注意:这个监听器不是用来监听系统资源的
定时器
定时器用于对每个操作时间设置等待时间,等待时间是性能测试中常用的控制客户端的手段,JMeter中定义了固定定时器、统一随机定时器、准确的吞吐量定时器等等定时器
前置处理器
用于在实际的请求触发之前对即将发出的请求进行特殊处理,例如HTTP URL重写修复符则可以实现URL重写,当URL中有sessionID一类的session信息时,可以通过该处理器填充发出请求的实际的sessionID
后置处理器
用于对发出请求后得到的服务器响应进行处理,一般用于提取响应中的特定数据
断言
断言一般用来检查测试中得到的数据(响应)是否符合预期数据
测试片段
测试片段是控制器上面的一个特殊的线程组,他在测试书上与线程组处于同一个层级,但是和线程组有些不同,因为他不会被执行,除非他是一个模块控制器或者是被控制器所引用时才会被执行
非测试元件
设置请求代理等一些非测试的元件
取样器(Sampler)
取样器是性能测试中向服务器发送请求,记录响应信息,记录响应时间的最小单元,JMeter原生支持多种不同的取样器,如HTTP Request Sampler(HTTP请求取样器)、FTP Request Sampler(FTP请求取样器)、TCP Request Sampler(TCP请求取样器)、JDBC TCP Request Sampler(JDBC请求取样器)等等,每一种不同类型的取样器都可以根据设置的参数向服务器发送不同类型的请求
逻辑控制器
逻辑控制器包括两类元件,一类是用于控制测试计划中取样器节点发送请求的逻辑顺序的控制器,常用的有如果(if)控制器,循环控制器、Runtime控制器、Switch控制器。另一类是用来组织可控制起洋气节点的,如事务控制器、吞吐量控制器等
JMeter脚本录制
JMeter原生脚本录制
JMeter的原生脚本录制有很多问题,录制的脚本中会有很多参数等是不完整的需要我们手动去添加等等,我们一般使用 badboy 工具进行脚本录制,并且可以把录制的脚本导出为JMeter脚本,然后直接导入到JMeter中就可以直接使用
HTTP请求+查看结果树
- 创建线程组->添加取样器->HTTP请求
- 添加结果树->在HTTP请求中添加请求的IP地址为:
www.baidu.com
->点击启动按钮->在结果树查看运行结果
- 创建一个HTTP代理服务器进行脚本录制
-
右键->添加非测试元件->HTTP代理服务器->修改我们的端口为8081->目标控制器选择我们新建的测试计划->分组选择每组放入一个新的控制器->点击启动
-
修改我们的浏览器设置,将代理设置为localhost:8081
-
访问
www.baidu.com
等待加载完成后点击停止录制 -
在我们的线程组中查看,就会发现很多请求都被录制到我们的的JMeter中了
-
HTTP代理服务器设置分组详解
- 不对样本分组:所有请求全部罗列
- 在组间添加分割:加入一个虚拟的以分割线命名的动作
- 每组放入一个新的控制器:执行时按照控制器给输出结果
- 只存储每组的第一个样本:保存第一次的URL请求
- 将每个组放入一个新的事物控制器中:
-
Badboy进行JMeter脚本录制
Badboy介绍
Badboy是一个强大的工具,包括捕获和回放界面,负载测试的支持,详细的报告图表等等,从而使web测试和开发变得更加容易
下载安装Badboy并且安装
-
下载我们一般直接百度搜索即可,应为官网已经打不开了,而这个工具也已停止维护很久了,可以使用列出的下载地址进行下载:http://xze.197946.com/badboy2.2.5.zip
-
下载好之后直接解压,并且一路下一步安装完成,打开软件
-
Badboy进行录制的时候可能会弹出一些提示框,这个是因为js的支持和解析错误导致的,我们可以在浏览器的Internet选项中点击搞基属性,进入到浏览标签,选中禁止脚本调试以及去掉启用脚本错误提示的复选框即可关掉一部分,但是有些还是会弹出来,目前暂时没有找到更好的处理办法,直接点是即可
脚本录制
- 点击红色的开始按钮,输入想要录制的网址即可开始录制
- 结束录制点击停止录制即可,然后点击file->Export to JMeter…->输入文件名称保存即可
JMeter元件作用域和执行顺序
元件作用域
JMeter中取样器是典型的不与其他元件发生交互的元件,逻辑控制器只对其子节点的取样器有效,而对其他元件(配置元件、定时器、断言、监听器)需要与取样器等元件互交
在JMeter中元件的作用域是靠测试计划的树形结构中元件的上下级关系来确定的,作用域原则如下:
- 取样器元件不和其他元件相互作用,因此不存在作用域问题
- 逻辑控制器元件只对其子节点中的取样器和逻辑控制器作用
- 除取样器和逻辑控制器元件以外,其他控制器如果是某个取样器的子节点,则该元件对其父节点起作用,如果其父节点不是取样器,则其作用域是该元件父节点下的其他所有后代节点(包括子节点以及子节点的子节点)
元件执行顺序
- 配置元件
- 前置处理元件
- 定时器
- 取样器
- 后置处理程序
- 断言
- 监听器
注意:前置处理器和后置处理器以及断言等元件功能对取样器的作用,因此,如果在他们的作用域内没有任何取样器,则不会被执行
如果在一个作用域范围内有多个同一类的元件,则这些元件按照他们在测试计划中的上下顺序进行执行
使用JMeter进行基础性能测试
测试需求
模拟50个用户访问百度,在负载达到60QPS时的平均响应时间
QPS:Query Per Second每秒查询率,是一台服务器每秒能够处理的查询次数,在互联网,一般域名服务器的性能我们经常使用每秒查询量(QPS)来衡量
添加线程组
- 线程组主要包含三个参数:线程数、准备时长(Ramp-Up时间(秒))、循环次数
- 线程数:可以理解为虚拟用户的数量,一个用户相当于一个线程,设置一个线程就类似于一个虚拟用户来操作
- 准备时长(单位秒):设置虚拟用户需要多少时间来全部启动,比如线程数为50,准备时长为5,则需要在5秒内启动50个线程也就是虚拟用户,相当于1秒启动十个线程
- 循环此处:我们设置为10次
- 添加取样器->HTTP请求
- 名称:这个HTTP请求的名称
- 注释:这个HTTP请求的注释
- 基本->web服务器:
- 协议:发送的请求协议,一般是HTTP或者HTTPS
- 服务器名称或IP:我们要请求的网址或者服务器IP地址
- 端口号:需要发送请求的服务对外暴露的端口号,在实际环境中一般都是使用80端口
- 基本->HTTP请求
- 方法:请求的方法类型
- 请求的路径地址:一般是端口号后面的地址
- 内容编码:我们要发送的请求编码,一般写UTF-8
- 自动重定向:JMeter会自动对301、302等重定向操作进行跟随,但是不会记录重定向的请求以及参数等等
- 跟随重定向:JMeter会自动对301、302等重定向操作进行跟随,与自动重定向不同,跟随重定向会对请求中的每个重定向进行记录,也可以回去到响应的数据等等,比如我们的登录重定向
- 使用KeepAlive:此选项用于JMeter和服务器之间使用Keep-Alive方式保持连接
1、HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议
2、从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接
3、Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间 - 对POST使用multipart/form-data:对于使用form表单提交的数据可以使用勾选此选项
- 与浏览器兼容的请求头:字面意思
- HTTP请求->高级
- 实现:我们请求的实现方式,调用我们请求的方式,可以选择java或者HTTPClient4去执行这个HTTP请求
- 超时(毫秒)
- 连接:HTTP发出连接请求的超时时间设置
- 响应:发送链接成功后服务器响应给我们的超时时间设置
- 从HTML文件嵌入资源:我们通过系列的设置可以对响应的HTML网页文件进行判断读取以及校验等等
- 源地址:我们请求的源的信息设置
- 代理服务器:设置请求的代理服务器
- 保存响应的数据为MD5哈希
设置QPS
JMeter给我们提供了QPS设置非常有用的定时器:常数吞吐量定时器、精准的吞吐量定时器,前者设置较为简单,后者可设置参数较多,更为精确
- 在HTTP请求取样器上面右键新增定时器->常数吞吐量定时器
- 设置目标吞吐量:此时需要注意单位转换,我们的QPS是每秒的吞吐量,需要换算成每分钟的,则要乘以60,我们需要设置的值为60*60=3600
- 下面的
基于计算吞吐量
的选择,我们可以根据我们实际情况进行设置,我们选择只有此线程
计算响应时间
上面的步骤设置完成后,我们基本完成了的设置就算是完成了,但是我们的需求是要计算响应时间,所以此处我们还需要在添加一个监听器,用于计算响应时间,JMeter中使用监听器元件来收集取样器记录的数据并以可视化的方式来呈现,我们此处添加一个聚合报告来查看结果
- 添加
聚合报告
:右键线程组->添加->监听器->聚合报告
- 添加
查看结果树
:右键线程组->添加->监听器->查看结果树 - 查看聚合报告
注意:上述中的时间单位均为毫秒
JMeter断言
断言就是检查接口的返回结果是不是我们预期的结果,对这两个结果的数据进行全量或者部分比对,这个过程我们称之为断言
添加断言
- 添加->线程组->添加取样器->HTTP请求
- 添加->断言->响应断言
- 添加->监听器->断言结果
- 添加->监听器->查看结果树
我们对我们的mock测试接口进行断言
- 添加HTTP请求的路径为:localhost:8888/demo
- 添加断言内容为:请求成功
- 运行,查看结果树中的断言结果
断言类型
- 响应式断言:对响应的内容进行断言
- JSON断言:对响应的json数据的某些值进行断言
- 大小断言:对响应的数据大小进行断言
- 断言持续时间:也就是超时断言
参数化
设置用户参数
- 添加->前置处理器->用户参数
- 在右侧用户参数添加变量,新增我们的参数
- 在HTTP请求中添加我们的参数
- 发送请求,检查我们的请求是否携带参数
设置CSV数据文件
- 添加->配置元件->CSV数据文件设置
- 函数的调用和上面的调用一致,JMeter的CSV数据可以不用写头部的key,只要我们的数据列顺序和我们设置的变量顺序一致即可
- 多条数据,可以直接使用JMeter的线程组进行多次调用即可
设置随机函数
- tools->函数助手对话框->选择_Random->设置我们的变量的最大数和最小数->点击生成->然后我们直接在我们需要使用的地方调用生成的函数即可
正则表达式提取器
使用
- 添加->后置处理器->正则表达式提取器
- 界面介绍,
- 要检查的字段:一般是我们请求响应的结果参数中我们需要提取的范围
- 引用名称:就是我们存放最终使用表达式提取出来的值的一个变量,方便我们调用
- 正则表达式:
() 括起来的部分是我们要提取的内容
. 匹配任何字符串
* 匹配任意长度
+ 一次或者多次
? 在找到第一个配项后停止
// 示例
{"code":200,"msg":"无参请求成功"}
// 如我们要取上面的json中的code的值,则可以使用如下表达式
code":?(.*),
- 模板:有时候我们可能使用表达式匹配出来不止一个,这个时候我们就可以使用模板来确定我们使用哪一个,如果使用匹配到的第一个则: 1 1 1
- 匹配数字:
0
代表随机取值,1
代表取全部值,我们一般使用1
即可 - 缺省值:表示如果正则表达式没有提取到值,则我们可以在此处给一个默认值
JMeter连接MySQL数据
有时候我们的测试数据可能存储在MySQL数据库,这个时候我们就需要使用JMeter来连接数据库进行数据获取进行测试
使用MySQL驱动文件连接MySQL数据库
- 准备我们的MySQL数据库,并创建一个新的数据库,创建新表,导入测试数据
- 准备MySQL的连接驱动文件jar包
- 下载地址: https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.48
- 下载地址: https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.48
- 点击测试计划,在最下面浏览添加我们的MySQL数据库驱动jar包
- 打开JMeter->添加->线程->线程组
- 添加->配置元件->JDBC Connection Configuration
- 配置JDBC连接
- Variable Name for created pool:配置变量名称,也就是后面我们调用的变量名称,可以随便填写
- Connection Pool Configuration:连接池配置
- Max Number of Connection:最大连接数,我们一般配置5-15左右即可
- Max Wait(ms):最大等待时间
- Time Between Eviction Runs (ms) :在被逐出的时间间隔(ms)。在空闲对象驱逐线程之间运行的毫秒数。当非正的时候,就不会运行无用的对象驱逐线程(默认为"60000",1分钟)
- Auto Commit : 将自动提交或关闭连接到连接上 。
- Taction isolation: 事务隔离
- **Preinit pool:**预初始化连接池
- Init SQL statements seqarated by new line:
- Connection Validation by pool
- **Test While Idle :**测试连接池的空闲连接
- Soft Min Evictable Idle Time(ms) : 软Min可驱逐空闲时间(ms)。在它有资格被闲置的对象驱逐者强制驱逐之前,一个连接可能闲置在池中,并且至少在池中存在空闲连接的额外条件,默认值为5000(5秒) 。
- **Validation Query :**验证查询 。一个简单的查询,用来确定数据库是否仍在响应。 这个验证查询在池创建中使用,即使“空闲测试”建议查询只在空闲连接上使用,也可以验证它。
- Database Connection Configuration:数据库连接配置
- **Database URL:**数据库的连接URL
## 模板
jdbc:mysql://数据库IP地址或者域名:端口号/连接的数据库名称
## 示例
jdbc:mysql://localhost:3306/jmeter
- **JDBC Driver class:**数据库连接驱动的类
## 直接写下面的即可,此代码标记了数据库驱动的类文件
com.mysql.jdbc.Driver
- **Username:**数据库连接用户名
- **Password:**数据库连接密码
- 查询数据进行校验
- 添加->取样器->JDBC Request->将我们刚才创建的MySQL连接的变量名称填写到变量中->编写sql语句进行数据查询
- 添加响应断言,对返回数据进行包括匹配断言->添加断言结果->添加查看结果树
- 添加->取样器->JDBC Request->将我们刚才创建的MySQL连接的变量名称填写到变量中->编写sql语句进行数据查询
JMeter函数
CSV文件读取函数-${__CSVRead(,)}
- tools->函数助手对话框->选择
_CSVRead
CSV文件我们直接填写本地CSV文件路径 - CSV文件号,我们填写我们要读取的列的数字,也可以使用随机数函数
- 点击生成函数,即可看到下面读取到的内容,复制函数使用即可
内容为中文时,会导致读取失败
随机数函数-${__Random(,)}
- 随机数函数用于生成随机数字,括弧中为前后边界值
- 使用时直接复制我们生成的函数到要使用的地方即可
#
读取文件函数-${__FileToString(,)}
- 读取一个文件的内容
HTTP属性管理器
因为JMeter并不是完全的浏览器,只是使用代码来模拟浏览器发送请求,JMeter为了工具的健壮性,在JMeter的配置元件中JMeter给我们提供了很多HTTP请求的相关的一些工具
HTTP信息头管理器(header头部信息)
- 这个头部信息是可以被多个线程组共用的
HTTP Cookie管理器
- 设置我们的请求中的cookie信息
HTTP缓存管理器
- 可以模拟类似于浏览器的缓存形式来缓存数据
HTTP请求默认值
- 请求默认值可以为我们一组线程提供默认的请求信息等等
逻辑控制器
ForEach控制器
- ForEach控制器用于循环读取变量等等操作
- 需要注意以下几点:
- 开始循环字段是不包含的
- 结束循环字段是包含的
- 循环的变量名称最好是
变量名称_数字
这样的格式
- 我们可以手动添加几组用户自定义变量(不是用户变量)用于验证
IF控制器
if类似于计算机语言中的if语句,可以根据一些表达式的值(true或者false)来判定是否执行执行等操作
For performance it is advised to check “Interpret Condiyion as Variable Expression” and user --jex13 or --groovy exaluating to true or false or a variable that contains or false. J M e t e r T h r e a d . l a s e s a m p l e o k c a n b e u s e d t o t e s t i f l a s t s a m p l e r w a s s u c c e s s f u l 为了提高性能,建议勾选“ I n t e r p r e t C o n d i y i o n a s V a r i a b l e E x p r e s s i o n ” , 并使用 − − j e x 13 o r − − g r o o v y 函数将结果计算为 t r u e 或 f a l s e 或者包含或 f a l s e 的变量。 {JMeterThread.lase sample ok} can be used to test if last sampler was successful 为了提高性能,建议勾选“Interpret Condiyion as Variable Expression”,并使用 --jex13 or --groovy函数将结果计算为true或false或者包含或false的变量。 JMeterThread.lasesampleokcanbeusedtotestiflastsamplerwassuccessful为了提高性能,建议勾选“InterpretCondiyionasVariableExpression”,并使用−−jex13or−−groovy函数将结果计算为true或false或者包含或false的变量。 {JMeterThread.lase sample ok}可用于测试最后一个采样器是否成功
- 我们将使用上面的循环,判断如果变量为李四则访问百度
循环控制器
- 此控制器可以控制子节点的循环执行次数
仅一次控制器
- 在我们有些接口中可能涉及多个线程,但是只有执行一次的,比如登录等操作,就可以使用此控制器使之子节点在多个线程中执行一次
事物控制器
事物控制器会生成一个额外的采样器来测量他下面的元素的总体执行时间,需要注意的是时间包含该控制器范围内的所有处理时间,而不仅仅是采样器的时间
事物控制器的作用:
想实现一个功能,但需要多个接口,这个接口需要上一个接口的数据做参数,我们数据都是单个的请求,对于这种一个功能包含多个请求的,我们就需要多个接口的请求时间相加在一起,我们不可能一个一个去添加,这时我们需要添加事务,这样会把此事务下的所有请求,都当作一个请求来计算。
- 我们可以添加一个线程,并创建事务控制器,在其下面添加3个HTTP请求,并使用聚合报告
- 在不勾选
Generat parent sample
的情况下我们发送请求
- 我们在勾选
Generat parent sample
的情况下去请求
可以发现,事物控制器在勾选
Generat parent sample
的情况下将我们下面的三个HTTP请求看做是他的子节点,只计算成一次,而在我们在不勾选的情况下,事物控制器会将下面的请求看成单个的,他会被聚合报告统计
注意:事物下有多个取样器,其中一个失败,则这个事物失败
JMeter生成测试报告
配置JMeter的环境变量
## 配置JMeter的安装目录变量
JMETER_HOME=自己JMeter的解压路径
## 配置path,在path变量中添加新的变量
%JMETER_HOME%\bin
## 配置CLASSPATH环境变量,在原有的后面添加如果之前没有,则需要新建,如果之前已经有了CLASSPATH,则需要在之前的后面加上我们JMeter的环境变量,需要注意的是每个环境变量之间需要用;分割
%JMETER_HOME%\lib\ext\ApacheJMeter_core.jar;
生成测试报告
打开cmd命令窗口并且定位到我们jmeter保存的文件后缀为.jmx
脚本位置,执行以下命令
jmeter -n -t test.jmx -l test.jtl -e -o D:/JMeter/ResultReport
## 命令参数详解
## -n :以非GUI形式运行Jmeter
## -t :脚本路径
## -l :运行结果保存路径(.jtl),此文件必须不存在
## -e :在脚本运行结束后生成html报告
## -o :保存html报告的地址, 名录下不可存在index.html文件,但是目录必须存在
## 如果已经生成了.jtl文件,则可以运行下面的命令生成报告
jmeter -g test.jtl -o D:/JMeter/ResultReport
## 在D:/JMeter/ResultReport目录下就会有我们的测试报告index.html文件,用浏览器打开即可
如果需要配置测试报告的生成,可以参考网上的一些配置方式,修改user.properties
即可