性能测试--联合使用jvisualVM与jmeter进行性能测试与接口性能分析

在使用PerfTest进行接口的测试之后,该工具可以进行简单的性能测试,但是对于http请求进行模拟不方便,趁这次机会,学习使用jmeter进行性能测试及分析。
之前用过jvisualVM,本次就结合jmeter一起,进行性能测试与原因分析。本篇文章分为两大部分:工具的配置与性能分析。
开发环境:mac pro,jdk 1.8.0,mysql innoDB(测试库,单server)


工具配置篇

1、Jmeter

1.1 使用终端打开jmeter,此处为绝对路径(当终端关闭时,jmeter也会一并关闭):

打开jmeter

1.2 新建测试计划


1.2.1 添加线程组
ramp-up period为执行后等待时间,设置为0则表明不暂停,一直执行;
循环次数若设置10,则总调用次数为线程数循环次数,
设置为永远后,则在手动暂停后才会停止调用,否则一直执行;

添加线程组

设置线程组


1.2.2 添加&设置模拟方式
由于本次测试为模拟http请求,因此使用如下设置:

添加模拟
设置模拟

其中路径内${phone}${openId}在后面有介绍,是本次压力测试的参数。

1.2.3 设置参数
两种方式,逐个手动设置与csv文件导入测试
1.2.3.1 逐个手动设置

添加单个参数
设置单个参数

其中添加变量即为添加参数,添加用户即为添加一组参数列表。

1.2.3.2 csv文件导入

添加csv文件
设置csv文件格式

其中filename内的路径为手动输入进去的,绝对路径,variable names为参数列表,csv格式如下:

csv文件格式


1.2.4 查看jmeter结果
调用详情与统计结果
1.2.4.1 查看调用详情–查看结果树

添加结果树

在调用成功之后,这里面就会有数据,上图左侧的调用返回结果格式设置为json。选择相应数据,即可看到每次请求的数据详情。

设置结果树


1.2.4.2 查看统计结果–聚合报告

添加聚合报告
查看聚合报告


2 jvisualVM

找到jdk所在安装目录,进入如下目录:

进入jv目录


2.1 设置远程服务器

2.1.1 由于本次使用远程服务器测试,需要设置远程服务器

添加远程主机


2.1.2 设置jmx端口

设置jmx端口


2.1.3 查找确定服务器jms端口
其中在查找jmx端口时稍微麻烦一点,由于不知道jmx或者jstatd端口,在服务器上grep了一把(实际是在配置文件内设定):

这里写图片描述

关于jmx服务有以下配置,其中端口为10826
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=10826

2.1.4 设置抽样器(已有测试结果)

设置抽样器

其中抽样器标签为设置及数据分析,点击右上角的设置后,即可设置仅分析的文件路径,即服务路径。还可设置抽样频率,频率越快,自然结果越准确,但是过快可能对系统造成额外负担,反而降低性能,这里采用默认的100ms。

经过以上设置,基础准备工作就做好了,下面就可以开始进行测试工作了

分析

3 测试与分析

3.1 启动jmeter,开始测试:

启动jmeter

其中绿色的三角标为开始执行,灰色六边形在开始执行后即变为红色,为停止执行按钮,再旁边的扫把即为清除之前的执行数据。

3.2 开始jvisualVm 采样

开始jvisualVm 采样

点击cpu后即开始采样,点击停止后,再点击下方的快照,会在左侧生成快照文件,稍后可以进行具体的分析。

查看快照

左侧打开快照文件,视图选择方法,即可看到具体方法所消耗的cpu时间占比。

3.3 设计case验证性能

本节主要是分析原有代码,研究提高该接口性能的方法。但是由于涉及到代码逻辑,因此就不予以展开了,但是可以有一个通用的开发、优化思路进行讨论分析。


3.3.1 缓存。
缓存这个话题有太多的点值得深入。毫无疑问,在抢红包这种场景下,缓存是必须存在的,我们如何使用好缓存呢?
3.3.1.1 创立空对象,避免短期缓存未命中对DB造成的压力。
try{
    //取缓存对象的值
    Object object = redisProxy.get(key,V.class);
    if(object != null && !(object instanceof NullObject)){
         …………
    }else{
        …………
        if(value != null){
            //放入缓存
            redisProxy.set(key,value, Constants.EXPIRE_48H);
         }else{
            // 空对象,存放1分钟,防刷
            redisProxy.set(key, new NullObject(), Constants.ONE_MIN);
        }
    }
}catch (Exception e){
    ……
}
这里的NullObject即为自定义空对象,可以有效避免短期缓存未命中对DB的压力。
3.3.1.2 高并发场景(相对)稳定的数据必须使用缓存。

对短期稳定的数据,可以通过设置缓存有效期控制。


3.3.2 可进行本地内存操作的逻辑前移,涉及到DB操作、外部接口调用的操作则后移,降低外部依赖时间。

在进行逻辑判断时,一般都遵循如下原则:
入参非空、合法性、正确性校验–>数据正确性、合法性校验–>调用外部接口–>DB操作–>返回

在实际操作中,可能会出现如下场景:

入参非空、合法性、正确性校验–>数据正确性、合法性校验–>调用外部接口–>DB操作–>…………数据正确性、合法性校验–>调用外部接口–>DB操作–>返回

那么在这里,我们可以将数据正确性、合法性校验与缓存结合起来。在保证系统运行的前提下,将通过缓存的数据校验操作前置,而必须操作DB的操作后移,这样可以在一定程度上降低DB的压力。

若合理利用单一职责原则,将判断逻辑与数据处理模块分离,那么代码维护与逻辑扩展也比较容易。


3.3.3 合理使用单一职责原则

这里只有一点,就是尽可能将判断逻辑与数据处理逻辑分离,让客户端尽快拿到结果。
考虑一种场景:若判断逻辑与数据处理分离,那么就可以单独提供一个类似于healthCheck的接口,快速判断该用户、该红包是否可抢,而不用在进行大段的逻辑处理之后,才返回客户端该用户不能抢红包。
关于这一段,我有一点体会,在上一家公司,当时有一个业务,判断逻辑日均调用500w+,而处理逻辑日均才几万的量。那么此时将判断逻辑单独行程一个接口,轻量级的,让接口快速返回结果。而处理逻辑在进行处理前,先锁定该数据,调用判断逻辑后再进行数据处理,经过测试,1000qps(秒杀、团购开始时)仍能正常对外提供服务。


4 其他

经过以上的流程,是不是觉得此时测试已经结束了?
其实不然,web服务一般都会涉及到db,如果有时间以及业务需要,还可以持续的进行测试,观察高qps场景下db的负载。
由于开发环境是单server的db,因此在低负载场景下,db的cpu使用率在10%左右。
而在20线程,450ms/每次调用(约40tps)的持续压力负载下,测试库db的cpu负载稳定在95%左右。
由于是测试库,无法与生产环境读写分离的集群数据库相比,但是仅仅是在20线程持续并发访问,开发库的cpu负载即飙升到95%。同时,在redis服务异常时保证服务可用,将是一个值得深入的话题。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值