abdstime 2020-04-10
Postman压测--------测试接口的稳定性
现如今,绝大多数项目,都采用前后端分离开发模式。
先是各自开发自己的部分,最后进行联调。在开发中,希望提早发现问题,尽早解决。
所以,对于后端【服务端】开发,需要学会模拟客户端调用,进而调试自己的代码。
Postman就是模拟客户端调用的常用工具。
当你需要验证你的接口的抗压能力的时候,可以点击Runner,进行压力测试。
对项目中的一个HTTP接口进行压力测试,以保证接口性能稳定性
预估的性能指标要达到200并发,500TPS。
在压力测试过程中,我们重点关注TPS、GC次数、CPU占用率和接口响应时间等指标。
》并发数
如:200并发,同时支持200个线程并发请求
》吞吐量TPS【】
》响应时间【请求到,返回结果所用时间】
压力测试就是用来确保服务的稳定,给出服务稳定极限条件。稳定指的是服务负载,cpu利用率,接口的响应时长,网络的延迟,结果准确性等等都在你的标准之内。而这些指标又相互影响。
每秒处理事务(TPS,Transaction Per Second)每秒系统处理事务(通过、失败以及停止)的数量。通过它可以确定系统在任何给定时刻的时间事务负载。
事务平均响应时间(Average Transaction Response Time)每一事务执行所用的平均时间,通过它可以分析测试场景运行期间应用系统的性能走向。
• 最大响应时间(Max Response Time)指用户发出请求或者指令到系统做出反应(响应)的最大时间。
• 最少响应时间(Mininum ResponseTime)指用户发出请求或者指令到系统做出反应(响应)的最少时间。
• 90%响应时间(90% Response Time)是指所有用户的响应时间进行排序,第90%的响应时间。
CPU(CentralProcessing Unit)中央处理器,是计算机的重要设备之一。功能主要是解释计算机指令以及处理计算机软件中的数据。
• CPU利用率(CPU Usage) CPU利用率分为用户态,系统态和空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间。平时所说的CPU利用率是指:CPU执行非系统空闲进程的时间/CPU总的执行时间。
内存(Memory) 也被称为内存储器,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。
• 内存使用率(Memory usage)内存占用率指的是此进程所开销的内存。
磁盘IO(Disk input/ output)磁盘的读写包速率。
网卡负载(Network Load) 网卡的进出带宽,包量。
压力测试(Stress Testing)是通过确定一个系统的瓶颈或者不能接收的性能点,来获得系统能提供的最大服务级别的测试
压力强度(pressure intensity) 指压力测试中对硬件的性能目标,比如系统的cpu利用率,内存使用率,磁盘I/O吞吐率,网络吞吐量等所施加的条件。
并发(Concurrent) 在操作系统中,指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。
并发用户数(the number of concurrent users )在同一时刻与服务器进行了交互的在线用户数量。
最大并发数(Maximum number of concurrent users)指同时登录站点的最大人数或者服务器同时接收下载的最大数量。
核实在保持配置不变的情况下,测试对象在不同操作条件(如不同用户数、事务数等)下性能行为的可接受性。
请求访问数量(VU 或RequestThread)指发送请求压力的数量
HTTP错误率(HTTP error rate)在选定时间段内,HTTP错误数量与请求数量的比率。
吞吐率(Throughput) 是场景运行过程中服务器每秒的吞吐量。其度量单位是字节,表示每个请求连接在任何给定的每一秒从服务器获得的数据量。
事务(Transactions) 事务是用户某一步或几步操作的集合。
1.切换环境变量窗口
2.查看环境变量
3.设置环境变量
原因1:为了方便切换不同环境。
原因2:为了变量传值。
如果接口1-----
会产生一个json串,如下所示:
{
"errorMsg": "",
"instanceId": "instance-52886563",
"trackUrl": ""
}
现在,下一个接口需要获取instanceId的值,传入接口中,获取值
为了自动化测试,把变量值放到变量中,进行传值。如下所示:
{{url}}/{{instanceId}}/state?userId=admin&accessId=cyj&accessKey=ak2&tenantId=antTenantId&db=default_dev
通过Tests测试脚本,获取接口返回值存入环境变量中。
Tests脚本如下:
pm.test("Status code is 200",function () {
var jsonData = JSON.parse(responseBody);
pm.environment.set("instanceId",jsonData.instanceId);
});
Json数据格式如下:
{
"errorMsg": "",
"instanceId": "instance-52886566",
"trackUrl": ""
}
后一接口,需要调用上一接口的返回值作为参数。
同时需要在http请求页,切换环境变量。
》接口响应时间
》接口响应结果正确性
注意:jmeter依赖jdk【个人使用jdk8】
》下载jmeter【apache工具】
》安装jmeter
下载zip文件,解压到安装目录,直接找到jmeter.bat文件【即可启动jmeter】
测试接口:
body传参:
{
"appName": "dsg-sampling",
"type": "batchsql",
"commandText": "use datago_dev;select * fromtwo_partitioned_by_time;",
"priority": 2,
"params": {}
}
当打开jmeter时,默认会根据template创建一个Test Plan.
先对测试计划进行保存--------选择一个目录-----文件名:demo_sdk.jmx
三个重要的参数:
Number Of Threads:线程数【并发用户】,模拟用户
Ramp-up Period:运行周期,如:1秒钟
Loop Count:请求次数
线程数是500,就是相当于有500个用户,运行线程的总时间是1秒。也就是说在这1秒中之内100个用户同时访问,每个用户循环一次,也就是访问一次。
设置ip,端口号,编码:
因为需要传参json,设置:Content-Type=application/json;charset=UTF
然后,点击save,进行保存。
注意:
当url中带有参数时,直接放到path中。
Json数据:放在bodyData中
一般在http上add.
目的是:展示接口响应结果,是否正确?
添加结果如下:
如:响应时间,错误率,吞吐量。。。
说明:一般在线程组下进行添加,只有点击运行,就会让所有http都运行result report.
通过表格,展示压测指标:
Average:平均响应时间
Min:最小响应时间
Max:最大响应时间
这个表格数据:汇总所有的http接口----同时,还可以导出表格数据【】
?
?
使用jmeter测试http接口,需要自动化验证接口返回结果是否符合我们的预期。
原来通过View Result Tree只能手动查看一个个接口,如下所示:
现在,我希望并发执行多个请求时,通过代码【断言】统一输出运行结果:
》有多少运行成功
》response code为200,但返回数据不符合预期
》response code 为200,返回数据也符合预期。
》有多少运行失败
》直接响应码不是200,明显报错。
这个目的,可能bean shell断言插件【工具】来达到目的。
Beanshell主要用来验证json数据是否符合预期。需要引入jmeter依赖json的jar包。
预期json:
{
"errorMsg": "",
"instanceId": "instance-52891107",
"trackUrl": ""
}
【下载json依赖包】
由于要解析json,那么就需要用到json相关的jar依赖包,下载地址:
http://download.csdn.net/download/xiaoxiao_renhe/10246640
如下所示:
1.首先运行Jmeter(可以直接运行\apache-jmeter-3.0\bin下的jmeter.bat或在CMD直接输入jmeter然后回车)
2. 创建jmeter测试计划
3.导入json依赖包
1.在"...apache-jmeter-3.0\bin"目录下新建dependencies文件夹,并将刚才下载下来的json依赖包(json-20140107.jar)复制进去,如下所示:
2.打开"...apache-jmeter-3.0\bin"目录下的jmeter.properties配置文件,搜索"plugin_dependency_paths=",删除该行的注释并设置为plugin_dependency_paths=../dependencies,最后保存;至此配置成功,在JMeter的BeanShell PostProcessor里就可以正常引用jar依赖包了。
3.不知道为什么有时候通过上述方法仍无法正常引用外部jar包,那么为了以防万一,强烈建议在测试计划中通过浏览将需要导入的jar包引入,如下所示:
然后,编写脚本:
import org.json.*;
//获取请求的返回code码
String responseCode =prev.getResponseCode().toString();
if(!"200".equals(responseCode)){
Failure =true;
FailureMessage = "创建实例接口,响应失败,响应code为:"+responseCode;
return;
}
String response =prev.getResponseDataAsString().toString();
JSONObject responseJson = new JSONObject(response);
//解析json对象
String message =responseJson.getString("errorMsg").toString();
if("null".equals(message) ||"".equals(message)){
Failure =false;
FailureMessage = "创建实例接口,响应成功,测试通过";
StringinstanceId = responseJson.getString("instanceId");
log.info("instanceId的值:" + instanceId);
return;
}else{
Failure =true;
FailureMessage = "创建实例接口,响应失败";
log.info("message的值:" + message);
return;
}
》判断responsecode是否200
》如果不是,直接断言失败,返回code
》如果是,获取json数据,解析json,验证是否符合预期
String response =prev.getResponseDataAsString().toString(); //获取上一个请求返回数据
JSONObject
= new JSONObject(response);
Prev:是jmeter内置对象
预期json:
{
"errorMsg": "",
"instanceId": "instance-52891107",
"trackUrl": ""
}
通过key:value形式获取value值,如:获取errorMsg,使用
String message =responseJson.getString("errorMsg").toString();
说明:
当符合预期时,设置
Failure = false; //表示断言成功,通过测试
FailureMessage = "创建实例接口,响应成功,测试通过"; //设置成功输出信息【只有当Failure设置为true时,才会打印出,实际意义不大】
当断言报错时,jmeter会当作接口请求失败,veiw result tree中展示报错,如下所示:
输出结果如下:
正确结果:
报错:实例不存在
{
"createTime": "",
"endTime": "",
"errorMsg": "NoSuchObjectException: 52886314",
"exitCode": -1,
"startTime": "",
"state": "",
"trackUrl": ""
}
2.state结果不为Success
{
"createTime": "1577949384000",
"endTime": "1577949462971",
"errorMsg": "",
"exitCode": 211,
"startTime": "1577949404306",
"state": "FAILED",
"trackUrl": "http://yarn-master-1:8088/proxy/application_1576845881305_2841/"
}
{
"createTime": "1578387559000",
"endTime": "",
"errorMsg": "",
"exitCode": -1,
"startTime": "",
"state": "PENDING",
"trackUrl": "http://yarn-master-1:8088/proxy/application_1576845881305_37367/"
}
import org.json.*;
//获取请求的返回code码
String responseCode =prev.getResponseCode().toString();
if(!"200".equals(responseCode)){
Failure =true;
FailureMessage = "创建实例接口,响应失败,响应code为:"+responseCode;
return;
}
String response =prev.getResponseDataAsString().toString();
JSONObject responseJson = new JSONObject(response);
//解析json对象
String message =responseJson.getString("errorMsg").toString();
String state = responseJson.getString("state").toString();
if(("null".equals(message) ||"".equals(message)) &&”SUCCESS”.equals(state) ){
Failure =false;
FailureMessage = "创建实例接口,响应成功,测试通过";
StringinstanceId = responseJson.getString("instanceId");
log.info("instanceId的值:" + instanceId);
return;
}else{
Failure =true;
FailureMessage = "创建实例接口,响应失败,状态为:"+ state;
log.info("message的值:" + message);
return;
}