简介
Jmeter, 由apache开源的一个非常成熟的压测工具
安装
在mac上,直接用homebrew
安装即可:
brew install jmeter
安装完成后,运行jmeter
命令即可启动jmeter可视化操作界面。使用jmeter -t your_script.jmx
可以指定脚本。
如果不想启动命令行,想直接执行脚本,并且输出结果,可以使用jmeter -n -t your_script.jmx -l result.jtl -e -o result
使用
Test Plan
一个新建的jmeter脚本文件,最外层为test plan,可以添加如下组件:
- Threads: 添加测试用的线程组
- Config Element: 添加一些整体配置,如http请求头,dns缓存等
- Listener: 一系列监听结果的可视化,如result tree, summary report等,包含错误率、吞吐、时延等数据
- Timer: 一些计时器
- Pre Processer: 在执行之前的操作
- Post Processer: 在执行之后的操作
- Assertion: 断言
Thread Group
一个执行的线程组,根据里面的配置可以实现并发请求:
- Number of Threads(users): 模拟多个线程(用户)同时发起请求,即并发数
- Ramp-up period(seconds): 启动时间
- Loop Count: 选择循环次数 常用的往thread group中添加的组件:
- Sampler
- BeanShell Sampler: java脚本。例如:
// 通过脚本设置一个变量id,值为uuid import java.util.UUID; UUID uuid = UUID.randomUUID(); vars.put("id",(uuid.toString()).toLowerCase().replaceAll("-",""));
- HTTP Request: 发送http请求
- BeanShell Sampler: java脚本。例如:
- Logic Controller: 添加一些逻辑操作,比如if-else,用来控制组件的执行流程
HTTP Request
一个实际执行的请求,通常可以对他的入参出参进行一些配置
- Config Element:
- HTTP Header Manager: 处理请求头等参数
- Pre Proccessors
- User Parameters: 用户参数模板
- Post Processors
- JSON Extractor: HTTP返回包JSON字段解析
请求的数据也可以使用之前预先生成的变量,例如入参为:
{
"id": "${id}",
"name": "test"
}
常用
- 添加的
Thread Group
除了有普通的Thread Group
,还有另外两种常用的:setUp Thread Group
: 在普通的线程组之前运行,通常用于进行一些前置的初始化流程。比如数据准备、token生成等等tearDown Thread Group
: 在普通的线程组之后运行,通常用于一些收尾操作,比如数据库清理、日志清理等
-
不同线程组中的变量是无法互通的,如果想要互通的话,需要通过脚本设置全局变量。例如组A通过http请求获得的返回包,通过
JSON Extractor
获得了组内的变量token
,那么为了让这个变量成为全局可用,可以:(1) 为http请求添加
Post Processors => BeanShell PostProcessor
,指定Parameters
为${token}
,并在脚本中将此值通过函数__setProperty
赋予给全局变量globalToken
:${__setProperty(globalToken, ${token}, )}
(2) 设置完之后,在其他的线程组想使用此全局变量时,就可以使用
${__P(globalToken)}
获取到对应的值
脚本开发
如果每次的脚本开发都是通过GUI的形式去开发,那么会面临几个问题:
- 每次一个微小的操作,都可能导致脚本发生改变,自己可能根本不知道改动了什么
- 对于历史的脚本难以做到归档
- 对当前的脚本需要仔细保存,一旦丢失,很难重新制作一个一模一样的脚本
为了彻底解决这个问题,最好的方式自然是使用jmeter自带的api来进行开发。我们可以保证同一份每次运行都能产生相同的脚本,并且通过git等管理工具,也能轻松重现历史版本的脚本。
官方的api可在这里查询: https://jmeter.apache.org/api/index.html。 maven的依赖参考如下:
<dependencies>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_config</artifactId>
<version>5.5</version>
</dependency>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_java</artifactId>
<version>5.5</version>
</dependency>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_http</artifactId>
<version>5.5</version>
</dependency>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_core</artifactId>
<version>5.5</version>
</dependency>
</dependencies>
仅生成脚本
public static void main( String[] args ) throws Exception {
// jmeter binary所在路径 我这边使用homebrew安装
String jmeterHomePath = "/usr/local/Cellar/jmeter/5.5/libexec";
JMeterUtils.setJMeterHome(jmeterHomePath);
JMeterUtils.loadJMeterProperties(jmeterHomePath + "/bin/jmeter.properties");
JMeterUtils.initLocale();
// 测试计划
TestPlan testPlan = new TestPlan();
testPlan.setName("Test Plan");
testPlan.setTearDownOnShutdown(true);
testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName());
testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName());
testPlan.setUserDefinedVariables((Arguments) new ArgumentsPanel().createTestElement());
// 在测试计划下,添加你的线程组等等
// ...
// 涵盖整个测试流程的哈希树
ListedHashTree tree = new ListedHashTree();
// 将测试计划加入树中
// 想表达树的父子结构,用这种写法: tree.add(testPlan, someThreadGroup);
tree.add(testPlan);
// 生成脚本 test.jmx
SaveService.saveTree(tree, new FileOutputStream("/path/to/save/your/jmeter/script/test.jmx"));
}
直接执行
如果想直接在程序内布置好结构树,不生成脚本文件,直接执行,可以这么做:
public static void main( String[] args ) throws Exception {
// 设置jmeter路径和构建测试树同上 省略
// 初始化jmeter engine
StandardJMeterEngine jme = new StandardJMeterEngine();
// 不生成脚本 而是直接执行
jme.configure(tree);
jme.run();
}
参考
- https://stackoverflow.com/questions/45320253/jmeter-share-setup-thread-group-variables-with-normal-thread-group
- https://stackoverflow.com/questions/56649473/construct-a-complex-jmx-file-from-java-based-on-jmeter-api
- https://stackoverflow.com/questions/19147235/how-to-create-and-run-apache-jmeter-test-scripts-from-a-java-program/42844065#42844065
- https://stackoverflow.com/questions/49197405/creating-a-new-jmeter-test-purely-in-java-ans-save-as-valid-jmx