测试工具之Fiddler Jmeter

310 阅读9分钟

性能测试指标

响应时间

  1. 用户客户端呈现时间
  2. 请求/响应数据网络传输时间
  3. 应用服务器处理时间
  4. 数据库系统处理时间

并发用户数

image.png

吞吐量

性能测试:指单位时间内系统处理用户的请求数
业务角度:可以用请求数/秒,页面数/秒,人数/秒来衡量
网络角度:可以用字节/秒来衡量
TPS:每秒事务数

系统性能计数器

性能计数器(counter)是描述服务器或操作系统性能的一些数据指标。计数器在性能测试中发挥着“监控和分析”的关键作用,尤其是在分析系统的可扩展性、进行性能瓶颈的定位时,对计数器的取值的分析非常关键。但必须说明的是,单一的性能计数器只能体现系统性能的某一个方面,对性能测试结果的分析必须基于多个不同的计数器。

思考时间

用户每个请求之间的时间间隔

Jmeter使用步骤

  1. 创建测试计划
  2. 增加线程组
  3. 添加http请求 可以添加http请求默认值,url等不用每次都填
  4. 参数填入
  5. 如果操作中不通过,需要cookie,可以先写登录接口,在使用jmeter中的httpcookie管理器添加cookie
  6. 断言
  7. 增加查看结果树或报告
  8. 运行

fiddler

原理:

Fiddler通过改写HTTP代理,让数据从他那里过来监控并截取到数据 image.png

前后端问题定位

第一种情况:fiddler 没有设置过过滤器没有抓到请求信息,可能是前端页面元素没有绑定事件,也有可能是前端发生了JS 错误,这就是前端的bug 。

第二种情况:若抓取到的请求返回的结果错误,我们要确认一下,是否是前端传输的数据是错的,是的话就是前端的bug ,如果确定传值是正确的话,那就是后端的bug 。

第三种情况:若抓取到的请求返回值中间的http 的状态码是500的话,说明是后端服务器一般的内部错误,那这就是后端的bug 。

第四种情况:若抓取到的请求返回值中间的http 的状态码是404的话,说明可能后端服务器根本就没有对应地址的服务,当然还有可能是前端JS 提交请求的时候提交了错误的地址。

jmeter基本操作

执行顺序
1. 配置元件
2. 前置处理器
3. 定时器
4. 取样器
5. 后置处理器
6. 断言
7. 监听器

image.png

参数:表单 变量 值

消息体数据:json xml 表单是 a=1 b=2 c=3

文件上传:上传文件

配置元件

http请求默认值 为http请求设置默认值

http消息头管理器

httpcookies管理器

http cache管理器

监听器元件

  1. 查看结果树:分析查看具体某一个请求的详情(分析错误请求的原因)
  • 请求头 请求体
  • 响应头 响应体
  1. 聚合报告(汇总统计)
  • 请求数,响应时间(平均的,min,max)单位ms
  • 错误率
  • 吞吐量
  • 发送接收 带宽
  1. 表格查看结果

  2. 图形结果

前置处理器

后置处理器

定时器

  • 思考时间-固定定时器
  • 同步定时器-集合点
  • 随机定时器
  • 吞吐量定时器

断言(注意放置的作用域)

参数化流程

  • 找出需要做参数化的数据
  • 提供数据源
  • 使用数据源数据把脚本里的常量变成变量

jmeter参数化方式

csv

image.png

  1. 新建txt文件,写入参数
  2. 在线程组中添加csv数据文件设置
    文件名:引用在文件创建的用户名和密码参数值的txt文件;
    变量名称:取给每列对应的数据取个变量名,通过${变量名}来获取参数值: image.png

函数助手

  1. 函数助手进行参数化,前期和csv一样都要提前创建好含有参数值的txt文件
  2. 对http请求添加函数助手
  3. 在函数助手页进行设置,选择功能
  4. 将函数助手生成的函数字符串添加到变量的值里面,此处为form格式,如下图所示: image.png
  5. 此处为json格式,如下图所示: image.png

使用场景:账号密码

手机号已存在

使用参数化技术。函数助手random,设置135开头的手机号码 最小值及最大值 拷贝代码

  • 函数式 随机数 time counter计数器
  • 变量 添加用户自定义变量IP 在其他地方可以${IP}
  • 编程式 引入外部jar java.class 使用beanshell编程

设置用户参数

1.在没设置用户参数之前,创建线程组

2.给用户添加变量:User parameters(用户参数): image.png 3.用户变量放在线程组上面,给变量设置值:

image.png 3.在http请求中,将固定的ip地址和端口号改成刚刚添加的变量名:image.png

用户自定义变量

1.给线程组添加自定义变量(User Defined Variables) 2.添加变量:

image.png 3.将http请求中的参数值替换为自定义变量:

image.png 4.运行

Jmeter接口关联

json path extractor

添加后置处理器变量为

image.png 添加debug(调式取样器) 查看是否拿到

在新增用户添加http请求头 添加参数名称和值

image.png

正则表达式提取器

  1. 一定要在查看结果树中的tester测一下,一般都是通过静态的边界值来定位动态的数据,将动态数据替换为(.*?)
  2. 在对应请求添加后置处理器-正则表达式提取器-名称为verify var verifyhash'(.*?)' 先存 image.png
  3. 查找所要替换的字段 替换为${verify} 或者手动去改 后用

参数

  • apply to:控制正则表达式提取器的作用对象

    • Main Sample:主请求
    • Sub Sample:子请求 最后一个子请求作为主请求来展示
  • 要检查的相应字段:指定数据的来源位置

    • 主体:默认值,对应查看结果树
    • 信息头:对应响应信息头
  • 引用名称:即变量名称,由用户自定义

  • 模板:可填写NN(位置变量,表示将第N对括号所对应的值存入变量)或常量字符串(NN以外的,即将字符串赋给变量)

  • 匹配数字:正整数N 表示将第N次找到的数据赋值给变量

    • 0(默认值) 表示随机抽取
    • -1 表示将所有数据以类似数组的形式存入变量数组

提取多个值保存为一个字符串 引用名称:name_value

正则表达式:name="(.?)" value="(.?)"

模板: 1 $$2$

输出:name_value=tomjerry

提取多个值分别保存

引用名称:name

正则表达式:name="(.?)" value="(.?)"

模板:$1

输出:name=tom

引用名称:value

正则表达式:name="(.?)" value="(.?)"

模板:$2

输出:value=jerry

遍历

①一次使用一个数据,使用N次可以用循环控制器或foreach控制器结合计数器使用

  • 添加循环控制器
  • 次数为${param_matchNr}(param是正则表达式的变量名称)
  • 添加计数器
  • 设置从1开始,递增为1,名称为index
  • 添加V函数
  • 在java请求中写入index{index} {V(param${index}.)}

②Allin 一次使用所有数据,使用一次,使用beanshell后置处理器

Jmeter集合点

让各个线程步调一致,对系统将进行加压,达到模拟真实并发访问的效果(synchronizing timer)
具体集合数不能大于线程数(没有超时一直等) 也不能小于线程数

image.png

image.png

Jmeter BeanShell

BeanShell是一种完全符合Java语法规范的脚本语言,是轻量级的Java脚本,所以BeanShell和Java是可以无缝衔接的。

特点

1、完整的Java语法的动态执行,Java代码片段,以及松散类型的Java和其他脚本

2、透明地访问所有Java对象和API

// BeanShell
// 注意这里的打印是打印到Jmeter的控制台了
System.out.println("Hello, World");

log 打印日志

log.info("lxq") //输出到jmeter的日志中 
log.error("lxq") 
System.out.println("java控制台的打印") //输出到控制台

2.vars操作jmeter变量(只能在当前线程组使用)

  • 用户定义变量
  • 正则表达式,json提取器
  • 定义变量

获取变量

log.info(vars.get("lxq")); 

设置变量

vars.put("www","yyy");

3.props存取jmeter全局静态变量(可以跨线程组)

log.info(props.get("jmeter.save.saveservice.output_format"));
props.put("aaa","bbb")

4.prov获取前面取样器的值

log.info(prev.getResponseCode());
log.info(prev.getResponseDataAsString());

5.ctx 上下文

Jmeter中的BeanShell

1、定时器:BeanShell Timer

2、前置处理器:BeanShell PreProcessor

3、采样器:BeanShell Sampler

4、后置处理器:BeanShell PostProcessor

5、断言:BeanShell Assertion

6、监听器:BeanShell Listener

image.png

BeanShell把关联转化为参数化

问题

问题一:参数化数据量不足,比如:我要压测的某个接口依赖登录,先通过登录获取到tokenId(每个账号登录一次),然后把tokenId作为被压测接口的入参,如果账号不足,当我并发的线程数多于登录账号数量,前一次登录获取到tokenId值将失效,导致使用旧的tokenId的请求失败;

问题二:依赖请求的存在,导致被压测的接口性能不准确;

想法

为了解决上面的问题,我们可以不用关联,先单独操作依赖的请求,把需要获取的关联值存到文件中,被压测的请求就用文件参数化获取关联值,被关联的值可能是有有效时间的,我们可以找开发帮忙把有效时间设置长点,比如24h,这样就不用频繁重新获取关联值保存到文件中,毕竟我们是压测,不需要关注关联值的有效期限。

解决方法

删除已存在的参数化文件tokenId.txt

注意:后面要生成tokenId.txt这个文件,如果这个文件存在,我们先删除。

beanshell脚本

String filename ="C:/tokenId.txt";
File file = new  File(filename);
if (file. exists())
     {
          file.delete();
     }

生成参数化的文件tokenId.txt

因为只有100个账号,所以线程数设置为100,循环次数设置为1,即每个线程运行一次

 

a.登录接口需要的csv参数化文件userInfo.dat

注意,此参数化文件中有两列,第一列是卡号,第二列是登录账号

登录获取参数化文件中的登陆账号userAccount,而卡号cardNumber是被压测接口需要的参数

 

b.登录请求 

正则提取tokenId

 

c.把关联获取到的值写入文件,因为被压测的接口需要用到tokenId和卡号cardNumber,所以需要把tokenId和卡号配对写在一行上,第一列是tokenId,第二列是卡号cardNumber

用包装流(BufferedReader)将字符输入流(FileReader)包装为缓冲字符输入流(BufferedReader)

生成的tokenId.txt文件,逗号分隔同一行的tokenId和卡号cardNumber两列数据

  被压测接口​脚本

这样,被压测接口就可以用上面生成的关联参数文件tokenId.txt了,下面变量名称和生成的tokenId.txt文件中变量顺序要一致

最终,我们就可以把脚本的重心完全放到被压测接口,而排除依赖接口的影响。

不同线程组之间的变量共享

思路:将某一线程组内的变量通过__setProperty函数设置成jmeter全局变量,在另一 个线程组中通过${__P(parameters)}函数调用即可。

说明:jmeter本身的内置函数中,__setProperty ({__setProperty(newtoken,{cookieKey},)})函数可以把某参数的值设置成jmeter本身的内置属性,而jmeter的内置属性是所有线程组都可以调用的,是全局变量。各个线程组调用时,只需使用调用jmeter属性的函数“${__P(parameters,)}”来调用相应的属性即可。

  1.在http请求下添加正则表达式提取器 :

  2.在请求下再添加Bean Shell PostProcessor(bean shell后置处理器)

image.png

    Parametres:把需要操作的参数传递给Bean Shell PostProcessor

    Script:  string cookie=bsh.args[0];     0是第一个值。

调用函数__setProperty,把Bean Shell PostProcessor中的参数cookie的值赋值给newcookie,并设置newcookie为jmeter内置属性。

   ${__setProperty(newcookie,${cookie},)};        

image.png

Jmeter压测准备

1.运行场景 看聚合报告

  • 响应时间
  • 错误率
  • 吞吐量

2.查看服务器资源 grafana看具体数据

发现问题 cpu使用率过高

  • sys
  • user 高 看哪个进程导致的
  • idle
  • io

3.看top资源查看具体哪个资源