dubbo的jmeter压测时jar包的热加载/动态加载

Posted 沧海一粟,何以久远

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dubbo的jmeter压测时jar包的热加载/动态加载相关的知识,希望对你有一定的参考价值。

在做dubbo的jmeter压测时,需要把jar包放入jmeter的lib/ext目录下,但是jmeter启动的时候会自动加载这个目录lib目录及lib/ext目录,这样启动后放入这些目录下的jar包就不会加载了。

jmeter的master--slave/client模式下,作为jmeter client,jmeter-server服务一直是启动的,当新的jar包放入client后,无法读取,因此需要client的jmeter动态加载这些新放入的jar包。

解决办法参考:http://blog.csdn.net/kekadm/article/details/51783240

 

继上篇文章《Jmeter+H2Database动态部署JAR包到代理端》实现了测试业务jar包的动态部署后,再不重启代理端Jmeter的情况下,jar的变化内容仍无法自动加载到Jmeter内存,所以还是不能实现一次启动,动态更新的目的。

 

因为,Jmeter在启动的时候会自动加载lib目录下的jar包,如果不重启,目录下更新的jar包也不能加载到内存。所以,要实现类的动态加载,必须在Jmeter测试类中实现业务类的重载。

 

即在Jmeter测试类中的setupTest()方法中要自定义代码实现业务类的加载。

 

此处以一个简单例子说明实现过程:

 

编写要被测业务类:TransDemo.java

 

package perftest.jmeter.trans;

 

public class TransDemo {

        

         public String action(){

                   Stringstr = "action1st.";

                   System.out.println(str);

                   return str;

         }

 

         public voidinit() {

                   System.out.println("testingstart....");

         }

 

         public voidend() {

                   System.out.println("testingover!!!!");

        

         }

}

 

将其导出为perftest-trans.jar,将这个包放到jmeter/lib目录以外的地方。如:c:/perftest-trans.jar (不能放在Jmeter/lib目录下)。

编写Jmeter测试类:TransDemoActions.java

package perftest.jemter.action;

 

import java.io.File;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.net.URL;

import java.net.URLClassLoader;

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.samplers.SampleResult;

 

public classTransDemoActions extends AbstractJavaSamplerClient{

    SampleResultresult= null;

   

    public Class<?>trans = null;

    Arguments    params= null;

    Method  methodInit= null;

    Method  methodAction= null;

    Method  methodEnd= null;

    MyClassLoader  classLoader= null;

    Object   newTrans= null;

    /**

     * 自定义类加载方法

     * @param jarpath

     * @param classpath

     */

    public void loadClass(String[] jarpath,Stringclasspath){   

        URL[]  urls= new  URL[] {};

        classLoader = new MyClassLoader(urls,null);

       

        try {

       

        for(String  jar:jarpath){

            classLoader.addJar(new File(jar.trim()).toURI().toURL());

            System.out.println("load jar file : "+jar.trim());

        }

           

            trans = classLoader.loadClass(classpath);

            System.out.println("load class file : "+classpath);

            methodInit = trans.getDeclaredMethod("init");

            methodAction = trans.getDeclaredMethod("action");

            methodEnd = trans.getDeclaredMethod("end");       

            boolean  accessible = methodInit.isAccessible(); 

            if(accessible ==false){

                methodInit.setAccessible(true);

            }

           

            newTrans = trans.newInstance(); 

        } catch (Exceptione) {

            e.printStackTrace();

        }

    }

    /**

     * 自定义jmeter外部参数

     */

    public Arguments  getDefaultParameters() {

        Arguments  params= new   Arguments();      

        params.addArgument("TRANS_JARPATH","c:/perftest-trans.jar");

        params.addArgument("TRANS_CLASSPATH","perftest.jmeter.trans.TransDemo");

        returnparams;

    }

   

    public void   setupTest(JavaSamplerContext arg0) {

        try {          

           loadClass(arg0.getParameter("TRANS_JARPATH").split(","),arg0.getParameter("TRANS_CLASSPATH"));           

            //通过反射调用TestDemo的init()方法,下同

            methodInit.invoke(newTrans);          

           

        }catch(IllegalAccessException   e) {

            e.printStackTrace();

        }catch(IllegalArgumentException   e) {

            e.printStackTrace();

        }catch(InvocationTargetException  e) {

            e.printStackTrace();

        }

    }

 

   

    @Override

    public SampleResult    runTest(JavaSamplerContextarg0) {

        try {

            methodAction.invoke(newTrans);

        }catch(IllegalAccessException  e) {

            e.printStackTrace();

        }catch(IllegalArgumentException   e) {

            e.printStackTrace();

        }catch(InvocationTargetException   e) {

            e.printStackTrace();

        }

        returnresult;

    }

   

    public void   teardownTest(JavaSamplerContext arg0) {

        try {

            methodEnd.invoke(newTrans);

        }catch(IllegalAccessException   e) {

            e.printStackTrace();

        }catch(IllegalArgumentException   e) {

            e.printStackTrace();

        }catch(InvocationTargetException    e) {

            e.printStackTrace();

        }catch (Exceptione) {

            e.printStackTrace();

        }

    }

    /**

     * 自定义内部类实现动态加载class

     * @author

     *

     */

    static class MyClassLoader extends URLClassLoader {

 

        public MyClassLoader(URL[]urls) {

            super(urls);

        }

 

        public MyClassLoader(URL[]urls, ClassLoader parent) {

            super(urls,parent);

        }

 

        public void addJar(URL url) {

            this.addURL(url);

        }

   }

}

 

将其导出为perftest-actons.jar,并将它放入<jmeterPath>/lib/ext下,在Jmeter启动时可以自动发现这个测试类: perftest.jemter.action.TestDemoActons 。

 

启动Jmeter,建立测试计划和添加线程组及“Java请求”

 

线程组大小设置为1,线程循环次数设置2:即一个虚拟用户进行2次迭代。

运行测试

 

运行测试可以看到System.out.println的输出结果:

技术分享图片

 

修改被测业务类TransDemo的action()方法

public String action(){

                   //此处修改打印输出字符

                   String   str = "actionsecond.";

                   System.out.println(str);

                   return str;

         }

 

重新将TransDemo.class打包为perftest-trans.jar,并覆盖前面的c:/perftest-trans.jar

 

重新运行测试

在不关闭和重启Jmeter的情况下,再次执行测试,可以看到输出信息已经改变为“action seconde.”:

 技术分享图片



小结:

所以要实现类的动态加载,必须在Jmeter测试类AbstractJavaSamplerClient(java请求)中使用URLClassLoader实现被测业务类的重新加载,并使用invoke()方法调用业务方法。

 

自此,通过《Jmeter+H2Database动态部署JAR包到代理端》及本篇可以为分布式测试中的众多代理端实现被测业务(jar)包的实时更新及业务测试类(class)的热加载。

 

再也不用重启100+台Jmeter代理端而烦恼了。技术分享图片



以上是关于dubbo的jmeter压测时jar包的热加载/动态加载的主要内容,如果未能解决你的问题,请参考以下文章

jmeter压测时内存问题

JMeter压测时如何在达到给定错误数量后停止测试

10_jmeter压测时jmeter报错socket closed

jmeter压测dubbo详解

Linux 当jmeter压测时,JVM内存泄漏,端口不够问题,解决办法

jmeter 压测之动态数据关联