Jmeter对服务端进行压测快速上手
安装
下载
安装jmeter的之前必须先装有JDK
官网下载地址:https://archive.apache.org/dist/jmeter/binaries/
jmeter3.0的对应jdk1.7,jmeter4.0对应jdk1.8以上,否者启用jmeter也会报错
配置
-  配置环境变量 
  
-  在系统变量PATH上加上: %JMETER_HOME%\lib\ext\ApacheJMeter_core.jar;%JMETER_HOME%\lib\jorphan.jar;%JMETER_HOME%\lib\logkit-2.0.jar;
-  汉化配置 
 打开jmeter文件目录下的bin目录的jmeter.properties,查找language=,将language修改为language=zh_CN
  
-  启动 
 双击jmeter目录下的bin目录下的jmeter.bat
 运行jmeter.bat的时候会出现cmd命令行窗口,这个窗口不能关闭,关闭之后会直接jmeter
基本使用
基本要素:
- 测试计划:项目名称
- 线程组:测试进程
- HTTP请求:需要压测的接口
工具栏部分功能说明

创建基本压测脚本
1.创建线程组

测试计划 ==> 鼠标右键 ==> 添加 ==> Threads ==> 线程组
线程组配置

| 参数 | 说明 | 
|---|---|
| 线程数 | 虚拟用户数量,一个线程代表一个虚拟用户数 | 
| Ramp-Up Period(in seconds) | 设置多长时间将线程数启动完毕。如果线程数为10,准备时长为5,则代表5秒内启动10个线程,即每秒启动2个线程 | 
| 循环次数 | 每个线程发送请求的次数。如果线程数为10,循环次数为5,则每个线程发送5次请求,总的请求(并发)为10*5=50。如果勾选了“永远”,则所有线程会一直执行,直到手动选择停止运行(最后一次运行结果是报错的) | 
| 持续时间 | 线程组发送请求持续的时间 | 
| 启动延迟 | 线程组延迟多久后启动 | 
2.创建HTTP请求

线程组 ==> 鼠标右键 ==> 添加 ==> Sampler ==> HTTP请求
HTTP配置

请求参数类型中的parameter、Body Data和Files Upload这三个只能选其中一个,不能混合使用
请求头设置
当请求参数是json格式时,需要额外设置请求头的Content-Type:

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

响应断言(可加可不加)
JSON 断言

HTTP请求 ==> 鼠标右键 ==> 添加 ==> 断言 ==> JSON Assertion
一般选断言返回的json数据

JSON表达式,可以参考:https://gotest.hz.netease.com/doc/jie-kou-ce-shi/xin-zeng-yong-li/can-shu-xiao-yan/jsonpi-pei/jsonpathyu-fa.html
断言持续时间
用来断言请求响应的时间,即使请求成功,如果超过了持续断言时间设置的值,那么该请求会被认为请求失败

在断言中配置响应的最大时间:

3.添加查看结果树
结果树可以查看每个请求的请求信息和响应信息

线程组 ==> 添加 ==> 监听器 ==> 查看结果树

绿色的为请求成功,红色的为请求失败,判断依据为添加的响应断言
结果树取样结果参数说明
| 参数 | 说明 | 
|---|---|
| Thread Name | 发送的线程名称 | 
| Sample Start | 发送时间 | 
| Load time | 加载时间,整个请求的消耗时间,从发送到接收完成全程消耗的时间 | 
| Connect Time | 建立连接时间 | 
| Latency | 等待时长,从请求发送到开始接收响应时的时间 | 
| Size in bytes | 发送数据的大小 | 
| Headers size in bytes | 请求头大小 | 
| Body size in bytes | 请求体大小 | 
| Sample Count | 请求发送数量 | 
| Error Count | 请求失败数量 | 
| Data type | 数据类型 | 
4.添加聚合报告
聚合报告是本次测试的总体报告

线程组 ==> 添加 ==> 监听器 ==> 聚合报告
聚合报告

报告参数说明:
| 参数 | 说明 | 
|---|---|
| Label | 请求名 | 
| #Samples | 并发数(线程数*循环次数) | 
| Average | 平均响应时间 | 
| Median | 中位数,50%请求的响应时间 | 
| 90% | 90%请求的响应时间 | 
| 95% | 95%请求的响应时间 | 
| 99% | 99%请求的响应时间 | 
| Min | 最小响应时间 | 
| Max | 最大响应时间 | 
| Error% | 在#Samples并发数量下的请求的错误率 | 
| Throughput | 吞吐量 | 
| Recived KB/sec | 每秒从服务器接收的数据量 | 
| Sent KB/sec | 每秒发送给服务器的数据量 | 
请求参数参数化
计数器
计数器用于创建一个顺序递增的参数

线程组 ==> 添加 ==> 配置元件 ==> 计数器
计数器配置

与每用户独立的跟踪计数器:每个请求独立一个计数器,当线程组有设置循环次数时,每个请求循环请求的计数器是独立的,都是从初始值根据递增值进行递增。如果不勾选该选项,则所有请求共用该计数器。
Maximum value:计数的最大值,当前的值由计数器计算下一次递增后超过最大值,则后面所有的请求都是当前的值,会从初始值重新开始递增。如初始值为1,递增为2,最大值为10,则计数器达到9的时候,下一次递增的值为11,超过了最大值10,则下一次计数从1开始重新递增
计数器使用

在HTTP请求中的请求参数,或者路径上都可与使用该计数器的值,使用的方式为:${计数器定义引用名称},如计数器定义的引用名称为num,则可以使用${num}来代表引用了计数器的值,需要注意的是,参数的数据类型,如果是字符串的话需要自行使用双引号包住引用的值
CSV数据文件
即引用外部数据文件来实现参数化

线程组 ==> 添加 ==> 配置元件 ==> CSV数据文件设置
CSV数据文件说明
csv文件跟Excel文件一样都是表格,除非可以创建csv文件,否则由Excel改后缀转成csv,读出来的数据都是乱码。解决方式是直接使用txt文件。内容如:

多列使用英文逗号隔开
CSV数据文件配置

变量名称:与数据文件中的表头无关,这里的变量名称是用来定义在线程组中使用该数据的变量名(读取数据文件是通过顺序读取,从左到右,所以需要保证数据文件的每一列数据对应上需要的变量名称),多个使用英文逗号隔开
CSV数据文件使用

- 与计数器的使用相同,在HTTP请求中的请求参数,或者路径上都可与使用CSV配置中的变量名称,也是同样${变量名称}的使用方式,也需要注意请求参数的数据类型
- 当数据文件中数据行数比并发量小的时候,会从头循环数据文件中的数据。如:并发数为5,数据文件只有3行,第一个请求用数据文件第一行的数据,第二个请求用数据文件第二行的数据,第三个请求用数据文件第三行的数据,当第四个请求发起的时候,数据文件没有第四行的数据,则会从第一行开始读起
其他常用组件
HTTP Cookie管理器
在请求中经常会遇到需要Cookie的场景,如登录后的tokenid存放在Cookie,可以使用HTTP Cookie管理器为来添加Cookie

线程组 ==> 添加 ==> 配置元件 ==> HTTP Cookie管理器
HTTP Cookie管理器配置

根据自己的需求添加Cookie即可,Cookie中的值也可以使用全局的变量名称来实现动态变化
HTTP请求默认值
如果多个请求的服务器地址、端口、协议都是同一个,可以使用HTTP请求默认值来处理

线程组 ==> 添加 ==> 配置元件 ==> HTTP请求默认值
HTTP请求默认值配置

-  像配置HTTP请求一样,但不需要填写请求路径 
-  后续填写HTTP请求时就不需要再填写协议、服务器地址、端口号和连接编码格式,只需要填写请求路径和请求方法即可 
  
-  如果Body Data中填写了共同参数,则请求会把这个请求参数拼入请求体中,但需要注意填写的格式,如上图HTTP请求默认值中填写了json格式的共同参数,包含了 current和pageSize两个参数,而HTTP请求中有独自请求参数,那最终的请求结果为:
  请求体变成了: {"studentName": "张三" }{"current": 1,"pageSize": 10 }
(目前想到的解决办法是各写一半,默认请求写下半段:
	"current":  1,"pageSize":  10
}
HTTP请求写上半段
{"studentName":  "${studentName}",
但这似乎有些另类并且不好维护)
定时器
当并发请求需要间隔时间发起请求时,可以使用定时器,这里介绍两种定时器
固定定时器
固定延迟指定时候后发起请求

线程组 ==> 添加 ==> 定时器 ==> 固定定时器

Uniform Random Timer定时器
随机定时器,随机延迟后发起请求,总体延迟时间 = 随机时间 + 常量时间

线程组 ==> 添加 ==> 定时器 ==> Uniform Random Timer
Uniform Random Timer配置

其他常见场景
多个请求顺序执行
在Jmeter中,在同一个线程组内,设置的请求是从上到下顺序执行的,也就是排得越靠顶部,越优先执行
使用上一个请求的请求结果作为下一个请求的请求参数
因为同一个线程组内,设置的请求是顺序执行的,经常会出现使用上一个请求的请求结果,作为下一个请求的请求参数。下面以新增后,根据新增的id进行详情查询为例讲解如何实现:

-  HTTP请求默认值:  
-  新增的HTTP配置 
  - 添加JSON Extractor -   在新增请求上 ==> 右键 ==> 添加 ==> 后置处理器 ==> JSON Extractor 
 
-  
- 配置JSON Extractor -   JSONPath表达式参考:https://gotest.hz.netease.com/doc/jie-kou-ce-shi/xin-zeng-yong-li/can-shu-xiao-yan/jsonpi-pei/jsonpathyu-fa.html 
 
-  
 
- 添加JSON Extractor 
-  根据id查询详情的HTTP配置  在请求参数中,使用 ${}来使用动态变量,这里使用${studentId},对应JSON Extractor中的的自定义变量名称
-  测试结果: -  第一个请求的响应: 
  
-  第二个请求的请求参数:  
 
-  
多个不同请求同时并发执行
一个测试计划下面可以有多个线程组,如果选择了工具类上的启动,则会启动所有的线程组,每个线程组的请求都是互不影响的。如果有多个请求不同请求同时并发的话,可以选择创建多个线程组来实现
一些JSONPath表达式
-  json数据体: {"code":200,"data":{"type":"String","name":"userName","value":"张三"} }获取到data中value的值: $.data.value
-  json数据体: {"code":200,"data":[{"type":"String","name":"userName","value":"张三"},{"type":"Integer","name":"age","value":18}] }获取到data数组中,第一个元素的value值 $.data[0].value
-  json数据体: {"code":200,"data":[{"type":"String","name":"userName","value":"张三"},{"type":"Integer","name":"age","value":18 }] }获取到name为userName的value的值: $.data[?(@.name=="userName")].value
-  json数据体: {"code":200,"data":{array:[{"type":"String","name":"userName","value":"张三"},{"type":"Interger","name":"age","value":18}]} }获取到array数组中name为age的value的值: $.data.array[?(@.name=="age")].value
