zoukankan      html  css  js  c++  java
  • Jmeter二次开发——基于Java请求

    简述

    这近几年,越来越多非http的协议需要进行性能测试,包括不仅限于各类rpc、mq、缓存等。对于这些协议,市面上可能没有现成的工具可以直接使用,这个时候,我们可以自己动手,通过编写相应的JavaSampler来高效地开展性能测试工作。

    环境准备

    • java环境已搭建ok
    • jmeter环境已搭建ok
    • idea开发环境已配置ok

    java和jmeter环境搭建,可参考Jmeter——环境搭建

    二次开发

    二次开发前提

    • 需要lib/ext中的ApacheJMeter_core.jar
    • 扩展java请求则还需要ApacheJMeter_java.jar
    • 扩展http请求则需要ApacheJMeter_http.jar

    导入jar包,自行导入,可参考IDEA的基本操作——导入导出jar包

    Jmeter Java Sampler

    方法简介

    public Arguments getDefaultParameters();                   可选,定义可用参数及默认值,获取界面的参数;
    public void setupTest(JavaSamplerContext arg0);            可选,测试前执行,做一些初始化工作,类似于LR的init和Junit中的setUp();
    public SampleResult runTest(JavaSamplerContext arg0);      必选,实现自定义请求,类似于LR的Action;
    public void teardownTest(JavaSamplerContext arg0);         可选,测试结束时调用,类似于LR的end和Junit中的tearDown();
    

    方法执行顺序

    getDefaultParameters() > setupTest(JavaSamplerContext arg0) > runTest(JavaSamplerContext arg0) > teardownTest(JavaSamplerContext arg0)

    常用方法

    • addArgument("name", "value") 定义参数
    • sampleStart() 定义事务的开始,类似于LR的lr_start_transaction,和LR一样事务间不要放无关代码
    • sampleEnd() 定义事务的结束,类似于LR的lr_end_transaction
    • setSuccessful(true、false) 设置运行结果的成功或失败,Jmeter统计成功失败的次数,在聚合报告中能够体现。

    类的继承

    在做二次开发的时候,大家都知道,自己定义的类需要继承AbstractJavaSamplerClient,可为什么要继承这个类,而不是其他,想必大家也都知道。为了能看的更明白,我们直接来看代码,如下所示:

    public abstract class AbstractJavaSamplerClient implements JavaSamplerClient {
        private static final Logger log = LoggerFactory.getLogger(AbstractJavaSamplerClient.class);
        private static final org.apache.log.Logger oldLogger = LoggingManager.getLoggerForClass();
    
        public AbstractJavaSamplerClient() {
        }
    
        public void setupTest(JavaSamplerContext context) {
            log.debug(this.getClass().getName() + ": setupTest");
        }
    
        public void teardownTest(JavaSamplerContext context) {
            log.debug(this.getClass().getName() + ": teardownTest");
        }
    
        public Arguments getDefaultParameters() {
            return null;
        }
    
        /** @deprecated */
        @Deprecated
        protected org.apache.log.Logger getLogger() {
            return oldLogger;
        }
    
        protected Logger getNewLogger() {
            return log;
        }
    }
    

    我们从上述代码看到有构造方法,3个普通方法,这3个方法是不是似曾相识?是的,在前文中就有提到。但发现,还少一个runTest方法,那它在哪呢?想必就是在这个类JavaSamplerClient中了。我们继续来看代码,如下所示:

    public interface JavaSamplerClient {
        void setupTest(JavaSamplerContext var1);
    
        SampleResult runTest(JavaSamplerContext var1);
    
        void teardownTest(JavaSamplerContext var1);
    
        Arguments getDefaultParameters();
    }
    

    好了,现在知道4个方法的来源了,在自己类中,实现功能,其实就是将这4个方法重写,来实现自己的功能即可。思路有了,我们就来真实来写个demo吧。

    getDefaultParameters

    编写getDefaultParameters()方法,使用addArgument方法,设置入参,代码示例如下:

    /**
         * 这个方法是用来自定义java方法入参的
         * params.addArgument("x","");表示入参名字叫x,默认值为空。
         * @return
         */
        @Override
        public Arguments getDefaultParameters() {
            Arguments params = new Arguments();
            params.addArgument("x","");
            return params;
        }
    

    该参数设置,在jmeter界面中会展示,如下所示:

    setupTest

    setupTest,做自动化、性能测试都有类似概念,就是在测试前执行,做一些初始化工作。示例代码如下所示:

        /**
         * 每个线程测试前执行一次,做一些初始化工作
         * 获取输入的参数,赋值给变量,参数也可以在下面的runTest方法中获取,这里是为了展示该方法的作用
         * @param arg0
         */
        @Override
        public void setupTest(JavaSamplerContext arg0) {
            x = arg0.getParameter("x");
        }
    

    runTest

    runTest是代码逻辑处理部分,示例代码实现的功能就是做数字简单的比较,demo而已,具体如下所示:

    /**
         * 真正执行逻辑的方法
         * @param arg0
         * @return
         */
        @Override
        public SampleResult runTest(JavaSamplerContext arg0) {
            SampleResult sr = new SampleResult();
            sr.setSamplerData("请求参数x的值为:"+x);
            try {
                // jmeter 开始统计响应时间标记
                sr.sampleStart();
                int sum = Integer.parseInt(x);
                if (sum<0){
                    logger.info(sum + "<0的值是"+ "-1");
                    // 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
                    sr.setResponseData("结果是:"+"-1", "utf-8");
                    //设置响应失败
                    sr.setSuccessful(false);
                }
                else {
                    String str = String.valueOf(x);
                    final StringBuilder builder = new StringBuilder(str);
                    if (builder.reverse().toString().equals(str)) {  //reverse 字符串反转,比如输入66,反转后为66,再做比较
                            logger.info(sum + ">0的值做比较后是"+ "0");
                            // 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
                            sr.setResponseData("结果是:"+"0", "utf-8");
                            sr.setDataType(SampleResult.TEXT);
                    }else {
                        logger.info(sum + ">0的值是"+ "1");
                        // 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
                        sr.setResponseData("结果是:"+"1", "utf-8");
                    }
                    //设置响应执行成功
                    sr.setSuccessful(true);
    
                }
                } catch (Throwable e) {
                    //有异常,执行失败
                    sr.setSuccessful(false);
                    e.printStackTrace();
                } finally {
                // jmeter 结束统计响应时间标记
                sr.sampleEnd();
            }
            return sr;
        }
    

    teardownTest

    teardownTest,与setupTest是对应关系,做自动化、性能测试都有类似概念,就是在测试结束后执行,做一些清理工作。示例代码如下所示:

    /**
         * 测试结束后调用
         * @param arg0
         */
        @Override
        public void teardownTest(JavaSamplerContext arg0) {
            SampleResult sr = new SampleResult();
            logger.info("测试结束");
            // 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
            sr.setResponseData("测试结束", "utf-8");
        }
    
    

    完成代码编写后,可以先调试一波,确保正确后,导出jar包,放到jmeter对应目录lib/ext下。导出jar包的操作,可参考IDEA的基本操作——导入导出jar包

    实际效果

    说了这么多,我们来运行下代码看下实际效果,启动jmeter,添加java 请求,并选择刚编写的java方法,如下所示:

    输出为-1

    先来演示输出为-1的效果,我们可以从代码中看出,结果为-1,输入值小于0即可。

    我们入参-9,如下所示:

    运行代码,通过结果树查看请求数据,如下所示:

    查看响应数据,如下所示:

    我们看接口响应情况,响应是失败的,为啥是失败的呢?我们从代码可知,入参小于0时,强制设置成了响应失败,执行效果如下所示:

    输出为1

    再来演示输出为1的效果,我们可以从代码中看出,结果为1,输入值大于0即可。

    我们入参78,如下所示:

    运行代码,通过结果树查看请求数据,如下所示:

    查看响应数据,响应的状态也是成功的,如下所示:

    输出等于0

    最后演示下输出为0的效果,我们可以从代码中看出,结果为0,输入值转换后还相等,则输出为0。

    我们入参66,如下所示:

    运行代码,通过结果树查看请求数据,如下所示:

    查看响应数据,响应的状态也是成功的,如下所示:

    完整代码

    再贴下今天演示demo的完整代码,如下所示:

    import org.apache.jmeter.config.Arguments;
    import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
    import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
    import org.apache.jmeter.protocol.java.test.JavaTest;
    import org.apache.jmeter.samplers.SampleResult;
    import org.apache.log4j.LogManager;
    import org.apache.log4j.Logger;
    
    /**
     * @author_router:wenyihuqingjiu
     * @date:2020-12-18
     * 
     */
    
    public class PalindromeDemo extends AbstractJavaSamplerClient {
        private static Logger logger = LogManager.getLogger(PalindromeDemo.class.getName());
        private String x;
    
        /**
         * 这个方法是用来自定义java方法入参的
         * params.addArgument("x","");表示入参名字叫x,默认值为空。
         * @return
         */
        @Override
        public Arguments getDefaultParameters() {
            Arguments params = new Arguments();
            params.addArgument("x","");
            return params;
        }
    
        /**
         * 每个线程测试前执行一次,做一些初始化工作
         * 获取输入的参数,赋值给变量,参数也可以在下面的runTest方法中获取,这里是为了展示该方法的作用
         * @param arg0
         */
        @Override
        public void setupTest(JavaSamplerContext arg0) {
            x = arg0.getParameter("x");
        }
    
        /**
         * 真正执行逻辑的方法
         * @param arg0
         * @return
         */
        @Override
        public SampleResult runTest(JavaSamplerContext arg0) {
            SampleResult sr = new SampleResult();
            sr.setSamplerData("请求参数x的值为:"+x);
            try {
                // jmeter 开始统计响应时间标记
                sr.sampleStart();
                int sum = Integer.parseInt(x);
                if (sum<0){
                    logger.info(sum + "<0的值是"+ "-1");
                    // 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
                    sr.setResponseData("结果是:"+"-1", "utf-8");
                    //设置响应失败
                    sr.setSuccessful(false);
                }
                else {
                    String str = String.valueOf(x);
                    final StringBuilder builder = new StringBuilder(str);
                    if (builder.reverse().toString().equals(str)) {  //reverse 字符串反转,比如输入66,反转后为66,再做比较
                            logger.info(sum + ">0的值做比较后是"+ "0");
                            // 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
                            sr.setResponseData("结果是:"+"0", "utf-8");
                            sr.setDataType(SampleResult.TEXT);
                    }else {
                        logger.info(sum + ">0的值是"+ "1");
                        // 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
                        sr.setResponseData("结果是:"+"1", "utf-8");
                    }
                    //设置响应执行成功
                    sr.setSuccessful(true);
    
                }
                } catch (Throwable e) {
                    //有异常,执行失败
                    sr.setSuccessful(false);
                    e.printStackTrace();
                } finally {
                // jmeter 结束统计响应时间标记
                sr.sampleEnd();
            }
            return sr;
        }
    
        /**
         * 测试结束后调用
         * @param arg0
         */
        @Override
        public void teardownTest(JavaSamplerContext arg0) {
            SampleResult sr = new SampleResult();
            logger.info("测试结束");
            // 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
            sr.setResponseData("测试结束", "utf-8");
        }
        
    }
    
    

    问题总结

    运行代码,报错提示没有LoggerFactory,报错如下所示:

    解决办法:重新下载slf4j包即可。

    以上就是今天的分享内容了,二次开发java请求,小小demo,有误之处,望批评指正。

  • 相关阅读:
    线程池。
    等待唤醒机制。
    第一册:lesson 131.
    线程同步机制。
    第一册: lesson 129。
    线程实现方式。
    第一册:lesson 125.
    第一册:Lesson 123.
    黄渤的谈话。
    K3 KFO 手册
  • 原文地址:https://www.cnblogs.com/hong-fithing/p/14098210.html
Copyright © 2011-2022 走看看