Jmeter按比例分配Api压测

Posted maerpao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jmeter按比例分配Api压测相关的知识,希望对你有一定的参考价值。

先看

【Jmeter】基础介绍-详细

【Jmeter】Request1输出作为Request2输入-后置处理器

继续聊提出的第二个问题,即

  2.需要按比例分配API请求并发,以模拟真实的API压力场景

做压测的时候,一般的需求都是多个API同时压,不然也看不出真正的tps是多少啊。

比如虽然接口a的需求并发不高,500个用户才请求一次,但是特别耗性能,导致其他接口tps下降严重,所以压测的时候可以将比例调的很小,但是不能忽略它,只测并发请求高的接口

说会主题,如何按比例分配压测并发量呢?使用Jmeter可以有两种实现方式

先说第一种,通过线程组的方式控制:

线程组1配置:

 线程组2配置:

 区别就是线程数不一样,当然用循环次数也可以控制,区别可以看【Jmeter】基础介绍-详细

Request请求:

 结果:

 这里哪个请求在前完全随机,两个线程中互不干扰。

这种方式的好处就是完全并行,互不干扰,缺点就是基本没有使用场景,一般情况下,API都是有权限认证接口的,后面的接口需要依赖前面接口的输出(实现方式可以看【Jmeter】Request1输出作为Request2输入-后置处理器),这种完全隔离的方式显然无法满足需求,或者你需要自己写代码提前获取登录信息,不使用压测过程中登录返回的认证信息。

我们继续介绍第二种方式,其实就是按【Jmeter】Request1输出作为Request2输入-后置处理器中创建的线程组一样,只使用一个线程组,然后通过循环控制器来控制某个Api所占比例:

新建循环控制器:

 调整参数达到按比例分配Api压力的目的:

 执行效果:

 如上图所示,执行了一个Request1和两个Request2,而且是按顺序执行的,即这种方式可以满足【Jmeter】Request1输出作为Request2输入-后置处理器需求的同时使用。不过有两点需要注意:

  1. 这种方式按顺序执行时,变量(例如身份信息token)是会被覆盖的,即无法完全模拟多用户登录及身份信息的场景。
  2. 这种配置方式会导致api并发分配不均,即在时间段1全部请求都是Request1,时间段2全部请求都是Request2,虽然总量是按比例的,但是并不符合我们的需求。

以上两个问题,在我的测试场景中1没有影响,即用户1、2、3、4、5那个来请求Api对压测来说是不关心的,性能完全一样。这里的登录只是为了压测登录接口,同时生成一个token给下面的接口使用。问题2影响比较大,可以通过【Jmeter】基础介绍-详细中提到的Ramp-up时间参数来控制,首先按比例配置好循环控制器后,将线程数和循环次数配置为1,Ramp-up配置为0,即立刻启动,然后使用压测机跑一下用于估算一次压测流程的时间。得到这个时间后,就是我们在实际压测中需要填写到Ramp-up中的参数,比如一次完整的压测流程需要2s,我现在需要压测执行1000个线程,循环100次,即一共10w次请求,将Ramp-up时间设置为2s,即1000个线程将在2s内逐步启动,达到所有线程的启动时间覆盖第一个线程一次循环的整个时间段,来达到真实模拟多种请求并发执行的过程,解决以上提到的第二个问题。

 

如何对N个接口按比例压测

随着微服务盛行,公司的服务端项目也越来越多。单一的接口性能测试并不能准确反映某个服务的总体处理能力,在服务功能划分比较清晰的架构下,对于某一服务的总体性能测试也相对变得简单。下面分享一个对于某个模块对应的服务的N个接口按照固定比例(来源于线上监控)进行性能测试,基于自己写的性能测试框架第二版

场景:该服务3个接口,比例为1:2:3。

这里为了保证请求不被线程共享,我使用了自己的重写的request深度拷贝的方法拷贝HttpRequestBase对象,这里一定要去做处理,不然线程共享会导致mark请求标记失败,一定要多注意一下Serializable接口的实现,不然会导致拷贝MarkRequest对象拷贝失败,request标记会混乱,还有一种办法就是重写MarkRequestclone()方法也行,如果是使用Groovy语言,建议选择后者。

    public static void main(String[] args) {
        def argsUtil = new ArgsUtil(args)
        def thread = argsUtil.getIntOrdefault(0, 2)
        def times = argsUtil.getIntOrdefault(1, 5)
        def split = argsUtil.getStringOrdefault(3, "1:2:3").split(":")

        def base = getBase()
        def flow = new Flow(base)
        flow.kSearch("测试")
        def request1 = FanLibrary.getLastRequest()
        flow.getPlatformK(12)
        def request2 = FanLibrary.getLastRequest()
        flow.getPaperType()
        def request3 = FanLibrary.getLastRequest()


        MarkRequest mark = new MarkRequest() {

            private static final long serialVersionUID = -2751325651625435073L;

            String m;

            @Override
            public String mark(HttpRequestBase request) {
                request.removeHeaders("requestid");
                m = m == null ? RString.getStringWithoutNum(4) : m
                String value = "fun_" + m + CONNECTOR + Time.getTimeStamp();
                request.addHeader("requestid", value);
                return value;
            }

        };


        def requests = []
        split[0].times {
            requests << new RequestThreadTime(request1, times)
        }
        split[1].times {
            requests << new RequestThreadTime(request2, times)
        }
        split[2].times {
            requests << new RequestThreadTime(request3, times)
        }
        List<HttpRequestBase> res = []
        thread.times {
            res << requests
        }

        new Concurrent(res, "对于模块**按照比例${split}压测线程数${thread}次数${times}").start()

        allOver();
    }

  • 郑重声明:文章首发于公众号“FunTester”,禁止第三方(腾讯云除外)转载、发表。

技术类文章精选

非技术文章精选

以上是关于Jmeter按比例分配Api压测的主要内容,如果未能解决你的问题,请参考以下文章

jmeter压测混合业务有先后顺序怎么处理

jmeter混合场景性能测试

如何对N个接口按比例压测

jmeter压测和抓包

转载Jmeter业务请求比例1

jmeter分布式压测对masterslave防火墙配置