当前位置 : 首页 » 文章分类 :  开发  »  Apache-JMeter

Apache-JMeter

JMeter 使用笔记
https://jmeter.apache.org/index.html


性能指标

TPS(Transactions Per Second) 服务器每秒处理的事务数
QPS(Queries Per Second) 服务器每秒处理请求数
响应时间(Response Time,RT) 处理一次请求的耗时

平响:处理一次请求的平均耗时

QPS = 并发数/平响(单位秒)
并发数 = QPS * 平响(单位秒)

单线程QPS公式:QPS = 1000ms/RT = 1/平响(单位秒)


压测方案设计

并发数逐渐增加,比如 100,200,300,统计 qps,平均响应时间
一般来说,随着并发逐渐增加:
1 qps 会先增加,再降低。增加是因为还没达到服务的最大负载,有资源闲置。降低是因为达到了服务的最大负载,再增加并发量只会拖慢服务。
2 平均响应时间 会逐渐增大,一开始低并发时变化率会较小,随着并发数到达服务的极限,平响增加的变化率会陡然升高。


页面压测方法

1、BadBoy 录制页面操作,导入到 jmeter,使用 jmeter 压测
2、JMeter 录制页面操作,jmeter 压测


使用 JMeter 进行页面录制及压测

1、测试计划->添加->线程(用户)->线程组

2、线程组->添加->逻辑控制器->录制控制器(Recording Controller)

3、测试计划->添加->非测试元件->HTTP代理服务器(HTTP(S) Test Script Recorder)
填入端口 8888

4、修改 Mac 网络代理配置,设置为 HTTP 代理 127.0.0.1 8888

5、JMeter HTTP代理服务器 中点 Start

6、点击需要录制的页面操作

7、点 Stop,录制控制器 中会记录页面操作调用的接口、js、css等(这一步骤我一直无法成功,无法录制到接口调用,貌似是网络代理配置搞错了)

8、保存 jmx 文件,使用 jmeter 命令压测。


使用 JMeter 进行 HTTP 接口压测

创建线程组

在“测试计划”上右键 -> 添加 -> 线程(用户) -> 线程组

1、并发数配置

<stringProp name="ThreadGroup.num_threads">100</stringProp>

2、如果想压测固定的时间:
循环次数(Loop Count)勾选“永远(Infinite)”,勾选“调度器”,填入持续时间秒
对应的 jmx xml 关键配置项如下,显示持续 300 秒

<intProp name="LoopController.loops">-1</intProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">300</stringProp>

3、如果想压测固定的循环次数:填入循环次数
对应的 jmx xml 关键配置项如下,循环 100 次

<stringProp name="LoopController.loops">100</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>

添加HTTP请求默认值

在刚创建的线程组上右键 -> 添加 -> 配置元件 -> HTTP请求默认值
填入要压测接口的 协议(http/https、url/ip、端口,这样之后所有的接口都不需要再填 url:port,修改也方便
当然也可以不用默认值,在每个 request 上写 ip port

添加HTTP头

线程组上右键 -> 添加 -> 配置元件 -> HTTP信息头管理器
填入公共 header,比如
Content-Type:application/json
accept: application/json

添加HTTP请求

在“线程组”右键 -> 添加 -> 取样器 -> HTTP请求
填入需要测试的 API 的请求路径和数据

添加响应断言

在 线程组 或 HTTP request 上点右键,Add > Assertions > Response Assertion
Apply to 应用范围,一般使用默认的 Main sample only。Main sample 代表主请求,Sub-samples 代表主请求下的子请求。
Field to Test 要测试的字段:Response Code
Pattern Matching Rules 匹配规则默认不变

  • 包括(Contains):响应数据包含预期值(相当于String的contains方法),则判定接口成功。支持正则匹配。
  • 匹配(Matches): 用正则表达式匹配返回结果,且必须能匹配整个返回值,而不是返回值的一部分。
  • 相等(Equals):响应数据与预期值完全相同才判定接口成功。不支持正则表达式。
  • 字符串(Substring):与【包括】类似,但不支持正则匹配。
  • 否(Not):取反,也就是前面【包括】等判定结果为true,断言结果为false。反之,前面判定为false,断言结果为true。
  • 或者(Or):勾选此项后,可以设置多个预期值,只要有一项判定成功,则断言判定成功 。
    Patterns to Test 添加期望的状态码: 200

断言的作用域:在线程组上创建断言,则该断言对线程组下所有取样器生效,而在取样器上创建,则只对该取样器生效。

然后可以添加 断言结果监听器 Thread Group > Add > Listener > Assertion Results
如果后续会添加 查看结果树 或 汇总报告 的话,结果树中也可以反映出断言是否成功

查看结果树

线程组上右键 -> 添加 -> 监听器 -> 察看结果树 Thread Group > Add > Listener > View Results Tree
之后运行线程组后,可通过结果树查看每个请求的结果

汇总报告

线程组上右键 -> 添加 -> 监听器 -> 汇总报告
之后运行线程组后,可通过 汇总报告 查看 qps,平响


Jmeter JMX 配置


ramp-up period

线程创建的启动时间,参数 ramp-up period 用于告知 JMeter 要在多长时间内建立全部的线程,默认值是 0
假如未指定 ramp-up period, 也就是说 ramp-up period 为零,JMeter 将立即建立所有线程,假设 ramp-up period 设置成 T 秒, 全部线程数设置成 N 个, JMeter 将每隔 T/N 秒建立一个线程。

假如设置成零,Jmeter 将会在测试的开始就建立全部线程并立即发送访问请求,这样一来就很轻易使服务器饱和,更重要的是会隐性地增加了负载,这就意味着服务器将可能过载,不是因为平均访问率高而是因为所有线程的第一次并发访问而引起的不正常的初始访问峰值,可以通过 Jmeter 的聚合报告监听器看到这种现象。
这种异常不是我们需要的,因此,确定一个合理的 ramp-up period 的规则就是让初始点击率接近平均点击率。当然,也许需要运行一些测试来确定合理访问量。

使用 JMeter 进行压力测试
https://www.cnblogs.com/stulzq/p/8971531.html


自增id(计数器)

线程组上右键 -> 添加 -> 配置元件 -> 计数器
名称:自增id
starting value:1
递增:1
引用名称:即变量名,id,之后可通过 ${id} 引用这个变量


时间函数

${__time(,)} 毫秒时间戳
${__time(/1000,)} 秒时间戳
${__time(yyyy-MM-dd,)} 日期

随机数

${__Random( param1,param2 ,param3 )}
param1 为随机数的下限
param2 为随机数的上限
param3 为存储随机数的变量名,是选填项。

随机字符串

${__Random( param1,param2 ,param3 )}
param1 生成的随机字符串长度
param2 随机字符取值集合
param3 为存储随机数的变量名,是选填项。

${__RandomString(40,abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789)}
${__RandomString(1,川鄂甘赣贵桂黑沪吉冀晋津京辽鲁蒙闽宁青琼陕苏皖湘新渝豫粤云藏浙使澳港)}

随机浮点数

比如想生成 0.xxxx 的四位小数,可以直接拼接 0.${__Random(0,10000)}


在几个自定义值中随机

添加 User Defined Variables(用户自定义变量)
编辑值
var1 xx
var2 xx
var3 xx

通过 ${__V(var${__Random(1, 3)})} 调用
解释:
${__Random(1, 3)} 随机生成1-3之间的整数
var${__Random(1, 3)} 随机生成 var1, var2, var3 中的任意1个字符串
最后通过 ${__V()} 对内部的变量求职,所以可以获得 var1 等自定义变量的值


JMeter使用CSV数据集

jmeter参数化、添加变量、生成随机数和导入csv文件数据
https://blog.csdn.net/zha6476003/article/details/80157874


jmeter 命令

官方建议尽量不要在 GUI 界面上直接进行压测,但其实小规模的也没关系,大规则的压测还是应该使用 jmeter 命令读取 jmx 配置进行:
1、在 jmeter GUI 界面上配置好压测的 线程组、request 参数,保存为 jmx 文件。注意保存时删除 查看结果树 和 汇总报告 两个监听组件,否则影响 jmeter 性能
2、使用 jmeter 命令行读取 jmx 文件进行真正的压测过程。

jmeter -n -t es-load-test.jmx -l jmeter-nongui.log -e -o webreport

-n, --nongui 非 GUI 模式 -> 在非 GUI 模式下运行 JMeter
-t, --testfile {argument} 测试文件 -> 要运行的 JMeter jmx 脚本文件
-l, --logfile {argument} 日志文件 -> 记录结果的文件
-e 生成压测报告仪表盘 dashboard (html网页)
-o 指定 dashboard 仪表盘页面的生成文件夹,必须不存在或是空目录

-h 帮助 -> 打印出有用的信息并退出
-r 远程执行 -> 在Jmter.properties文件中指定的所有远程服务器
-H 代理主机 -> 设置 JMeter 使用的代理主机
-P 代理端口 -> 设置 JMeter 使用的代理主机的端口号

1.4.4 CLI Mode (Command Line mode was called NON GUI mode)
https://jmeter.apache.org/usermanual/get-started.html#non_gui


环境变量

JVM_ARGS

默认为空,可自定义 jvm 参数。

比如运行 jmeter 命令前通过 JVM_ARGS 配置堆内存大小:

JVM_ARGS="-Xms1024m -Xmx1024m" jmeter -t test.jmx [etc.]

或者可直接修改 bin 目录下的 jmeter 可执行文件,这是个脚本。

HEAP

jvm 堆内存参数, 默认是 -Xms1g -Xmx1g -X:MaxMetaspaceSize=256m

也可以通过 HEAP 环境变量设置堆内存大小:

HEAP="-Xms1g -Xmx2g" jmeter -t test.jmx [etc.]

JMeter OutOfMemoryError

问题:
jmeter 压测执行完,最后整理数据导出报告时发生 oom,报错如下:

Tidying up ...    @ Fri Jan 28 08:56:21 CST 2022 (1643331381955)
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid3047.hprof ...
Heap dump file created [1007413454 bytes in 1.513 secs]
Uncaught Exception java.lang.OutOfMemoryError: Java heap space in thread Thread[StandardJMeterEngine,5,main]. See log file for details.

原因:
添加了监听器、报告导出,比较耗内存,内存不够用了
JMeter 的 OOM 和请求量大小有关,分配同样的 jvm 堆内存,请求量小可能没事,但请求量大(比如持续压测几十个小时)时,最后 Tidying up 时就可能报 OOM。
Tidying up 报 OOM 只会导致 web 报告生成失败,不影响压测过程,没有 web 报告还可以通过压测过程中输出的每分钟 TPS 和 平响统计大致了解下性能。

解决:
jmeter 执行时会读取 HEAP 环境变量,默认值是 -Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m
执行 jmeter 前修改 HEAP 环境变量 HEAP="-Xms1g -Xmx2g" jmeter -n -t es-load-test.jmx -l jmeter-nongui.log -e -o webreport jmeter 中会自动读 HEAP 来设置 jvm 堆内存大小。


implementation 客户端实现

Java 和 httpClient4 的区别

JMeter的Java implementation无法统计network send

1、JMeter 的 java 客户端实现不会统计 bytes sent,httpClient4 客户端会统计,所以用 Java implementation 时最后的压测报告页面上 network sent 都是0.
2、有时候 httpClient4 客户端会出现 Non HTTP response code: org.apache.http.NoHttpResponseException 异常,但改用 java 客户端就没事。
3、java客户端连接是复用的(代码中的http调用都加了连接池),从JMeter 5.0开始默认使用httpClient4,JMeter将在每个线程组迭代时重置HTTP状态(SSL状态+连接),可设置httpclient.reset_state_on_thread_group_iteration = false 取消每次重置连接。

Difference in sent bytes and connect time for Java and HTTP Client 4 implemenation in JMeter
https://stackoverflow.com/questions/54769887/difference-in-sent-bytes-and-connect-time-for-java-and-http-client-4-implemenati


BeanShell Java脚本

BeanShell 是一种完全符合 Java 语法规范的脚本语言,并且又拥有自己的一些语法和方法
BeanShell 是一种松散类型的脚本语言(这点和 JS 类似)
BeanShell 是用 Java 写成的,一个小型的、免费的、可以下载的、嵌入式的 Java 源代码解释器,具有对象脚本语言特性,非常精简的解释器 jar 文件大小为175k。
BeanShell 执行标准 Java 语句和表达式,另外包括一些脚本命令和语法。

BeanShell 官网
http://www.beanshell.org/

beanshell / beanshell
https://github.com/beanshell/beanshell

Jmeter 有哪些地方可以使用 Bean Shell?
定时器: BeanShell Timer
前置处理器:BeanShell PreProcessor
采样器: BeanShell Sampler
后置处理器:BeanShell PostProcessor
断言: BeanShell断言
监听器: BeanShell Listener

JMeter 中可以在请求前增加预处理器(PreProcessor),在请求后增加后处理器(PostProcessor)

比如我们想让变量 randomOption 是字符串 cat, dog, parakeet 三者中的随机一个,可以这样写:

String[] query = new String[]{"cat", "dog", "parakeet"};
Random random = new Random();
int i = random.nextInt(query.length);
vars.put("randomOption",query[i]);

Jmeter之Bean shell使用(一)
https://www.cnblogs.com/puresoul/p/4915350.html


JMeter 中 BeanShell 调用Java的三种方式

jar包

用法:
把需要的工具类打成 jar 包,放在 %JMETER_HOME%/lib/ext 目录下
import 类名; 即可使用

import com.MD5;

String strMd5 = MD5.GetMD5Code("123456");

class文件

用法
addClassPath(“ class 文件所在目录”);
import 类名;

addClassPath("C:\\");  //"可以是父级目录或者祖先级目录"
import com.MD5;

String strMd5 = MD5.GetMD5Code("123456");

java文件

语法
source(" java 文件路径")

source("E:\\eclipse\\workspace\\MD5\\src\\jmeter\\MD5.java");
// source("MD5.java");  //文件位于 jmeter bin 目录下

String strMd5 = MD5.GetMD5Code("123456");

【JMeter】Beanshell 调用 java 代码的三种方式
https://blog.csdn.net/lijing742180/article/details/86213875


JMeter 中使用 BeanShell 设置签名

Jmeter通过beanshell对http消息进行签名
https://www.cnblogs.com/zgq123456/articles/11146443.html


Linux 安装 JMeter

1、下载 jdk 1.8
https://www.oracle.com/cn/java/technologies/javase/javase8-archive-downloads.html

2、安装 jdk 1.8 rpm -i jdk-8u202-linux-x64.rpm

# java -version
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)

3、官网下载 apache-jmeter-5.3.tgz
https://jmeter.apache.org/download_jmeter.cgi

4、编辑 /etc/profile 添加 jmeter 环境变量
最后添加 export PATH=/path-to/jmeter/bin/:$PATH
source /etc/profile 使生效

5、任意位置执行 ./jmeter --version 有结果即可

# ./jmeter --version
    _    ____   _    ____ _   _ _____       _ __  __ _____ _____ _____ ____
   / \  |  _ \ / \  / ___| | | | ____|     | |  \/  | ____|_   _| ____|  _ \
  / _ \ | |_) / _ \| |   | |_| |  _|    _  | | |\/| |  _|   | | |  _| | |_) |
 / ___ \|  __/ ___ \ |___|  _  | |___  | |_| | |  | | |___  | | | |___|  _ <
/_/   \_\_| /_/   \_\____|_| |_|_____|  \___/|_|  |_|_____| |_| |_____|_| \_\ 5.3

Copyright (c) 1999-2020 The Apache Software Foundation

Intel/M1 Mac brew 安装 JMeter

brew install jmeter

brew install jmeter --with-plugins
Intel Mac 安装目录 /usr/local/Cellar/jmeter/5.0,安装后有 /usr/local/bin/jmeter 链接到 /usr/local/Cellar/jmeter/5.0/bin/jmeter
M1 Mac 安装目录:/opt/homebrew/Cellar/jmeter/5.4.3,安装后有 /opt/homebrew/bin/jmeter 链接到 /opt/homebrew/Cellar/jmeter/5.4.3/bin/jmeter
安装后可直接全局执行 jmeter 命令

运行JMeter图形界面

全局执行 jmeter 命令即可打开 JMeter 图形界面
由于 brew 安装 jmeter 后会自动将可执行程序链接到系统path,所以在任意目录执行 jmeter 即可启动JMeter界面

~: jmeter
================================================================================
Don't use GUI mode for load testing !, only for Test creation and Test debugging.
For load testing, use NON GUI Mode:
  jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]
& increase Java Heap to meet your test requirements:
  Modify current env variable HEAP="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m" in the jmeter batch file
Check : https://jmeter.apache.org/usermanual/best-practices.html
================================================================================

Mac JMeter 界面中文乱码

如果 JMeter 界面语言是英文,浏览打开 jmx 文件时,目录和文件名中的中文都是乱码,所以需要将界面语言改为中文。

方法1,临时修改
出现中文乱码,是因为语言与外观不兼容导致,语言选“中文”,外观选“Metal” 即可。但重启 JMeter 界面后又会变为英文。

方法2,永久修改
编辑 /usr/local/Cellar/jmeter/5.3/libexec/bin/jmeter.properties
修改第 39 行,改为中文 zh_CN
修改第 1086 行,编码格式改为 UTF-8

#Preferred GUI language. Comment out to use the JVM default locale's language.
language=zh_CN

# The encoding to be used if none is provided (default ISO-8859-1)
sampleresult.default.encoding=UTF-8

Mac JMeter 无法黏贴

这是 jmeter 默认主题 Dracula 的 bug,切换主题,Options -> Look and Feel -> 改为 System 主题即可。

M1 Mac JMeter 无法保存jmx

点击保存 或 另存为,命令行报错
Uncaught Exception java.lang.NoClassDefFoundError: Could not initialize class org.apache.jmeter.gui.util.FileDialoger in thread Thread[AWT-EventQueue-0,6,main]. See log file for details.
这是 jmeter 默认主题 Dracula 的 bug,切换主题,Options -> Look and Feel -> 改为 System 主题即可。


异常


NoRouteToHostException

Non HTTP response code: java.net.NoRouteToHostException/Non HTTP response message: 无法指定被请求的地址 (Address not available)
Non HTTP response code: java.net.NoRouteToHostException/Non HTTP response message: Can’t assign requested address (Address not available)

原因:Jmeter 发压机的端口不够用,即客户端的端口不够用。

解决:
一、Linux 上
(1) 修改 ipv4.ip_local_port_range,增大可用端口范围
cat /proc/sys/net/ipv4/ip_local_port_range 查看可使用的端口范围,默认值是 net.ipv4.ip_local_port_range = 32768 61000
执行 echo 1024 65000 > /proc/sys/net/ipv4/ip_local_port_range 改为 net.ipv4.ip_local_port_range = 1024 65535
执行:sudo sysctl -p ,使设置立即生效。

(2) 修改 /etc/sysctl.conf 编辑文件,加入以下内容:

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30

然后执行 sudo sysctl -p 让参数生效。

net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;tcp_tw_reuse 设置在大量短连接打开并处于 TIME_WAIT 状态的环境中特别有用,例如 Web 服务器。重用套接字可以非常有效地减少服务器负载。
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间

二、Mac OS 上
参考 MAC使用笔记 Mac OS 最大连接数和端口范围配置

Jmeter 遇到的问题:rc=”Non HTTP response code: java.net.NoRouteToHostException” rm=”Non HTTP response message: Cannot assign requested address”
http://ferriswheelgyh.blogspot.com/2016/12/jmeter-rcnon-http-response-code.html

JMeter 进行压力测试
https://my.oschina.net/shichangcheng/blog/1560864

How to avoid a NoRouteToHostException?
https://stackoverflow.com/questions/1572215/how-to-avoid-a-noroutetohostexception


HttpHostConnectException Connect to ip failed Connection timed out

jmeter 压测报错

Non HTTP response code: org.apache.http.conn.HttpHostConnectException/Non HTTP response message: Connect to 10.153.108.12:8380 [/10.153.108.12] failed: Connection timed out (Connection timed out)

一般来说,原因是由于服务端有较多请求正在处理(且处理时间较长),导致 JMeter 不能连接上服务器而产生的。


上一篇 QPS和TPS

下一篇 TiDB

阅读
评论
4.6k
阅读预计19分钟
创建日期 2018-12-08
修改日期 2022-12-05
类别

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论