在做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包的热加载/动态加载的更多相关文章

  1. Dubbo-使用Maven构建Dubbo服务的可执行jar包

    一.为什么要构建Dubbo服务的可执行jar包? 1.1 Dubbo服务运行方式比较 ✎使用Servlet容器运行(Tomcat.Jetty等)  ---不可取 --缺点:增加复杂性(多了容器的端口) ...

  2. 使用jmeter实现对jar包的调用

    一.前言 在我们测试接口的过程中,可能有时需要用到第三方jar包来生成一些测试数据(如有时需要对参数的输入值使用第三方jar包进行加密操作),涉及到这种的情况,普遍做法是:手动调用jar包获得需要的值 ...

  3. Jmeter引用外部jar包的几种方法

    总结记录下jmeter引用外部jar包的3种方法及其优缺点: 一.测试计划中添加目录或jar包到Classpath 操作:测试计划->添加目录或jar包到Classpath-->浏览导入j ...

  4. jmeter maven自动移动jar包windows 批处理命令

    jmeter项目maven文件下面放这.bat 工具,可以把必要的jar包移动到jmeter响应的文件夹下面 rem 本文件放在jmeter 脚本maven项目根目录下面,和pom.xml在同一个文件 ...

  5. 跟我学习dubbo-使用Maven构建Dubbo服务的可执行jar包(4)

    Dubbo服务的运行方式: 1.使用Servlet容器运行(Tomcat.Jetty等)----不可取 缺点:增加复杂性(端口.管理) 浪费资源(内存) 官方:服务容器是一个standalone的启动 ...

  6. 【JMeter】Jmeter引入第三方jar包

    Jmeter做remoteService,里面用到一个实体:clickEntity,是在一个第三方jar包定义的:com.bj58.opt.ad_logparser-0.0.18-SNAPSHOT.j ...

  7. Jmeter调用自定义jar包

    一. 场景 在测试过程中, 可能需要调用第三方jar包来生成测试数据或者使用java工具类来实现业务场景, 普遍的做法是手动调用jar包, 再把这些值赋给jmeter中的某个参数, 以满足业务测试需求 ...

  8. SpringBank 开发日志 使用maven构建dubbo服务的可执行jar包

    写这篇日志的时候,我已经完成了这个目标,并且中间经历了一次面试.现在回过头看,已经觉得印象不那么深刻了,果然还是一边思考,一边记录这样最好.但我还是严格要求自己,从新做了梳理,对相关配置进行了整理和说 ...

  9. jmeter引入外部jar包的方法

    jmeter最完美的jar包引入 第一步:需要新建一个文件夹用来存放需要引用的外部jar包,例如:建一个dependencies 文件夹 第二步:jmeter 的配置文件 jmeter.propert ...

随机推荐

  1. markdown表格中怎么插入逻辑或符号|?

    | 73向下投票接受 | 如果你删除反引号(****),使用|`黑客作品 a | r ------------|----- `a += x;` | r1 a |= y; | r2 并产生以下输出 在这 ...

  2. Node.js——fs常用API

    文件状态 文件删除 文件信息 读取文件夹 文件的截取 创建文件夹 删除目录 文件监视,可以设置监视频率 文件重命名,可以用来剪切文件 注意 fs.open() fs.close() 这是最原始的读写方 ...

  3. 关于ubuntu16.04系统无法系统更新的解决

    1.提示系统更新升级,报错 /boot空间不足 2.根据网络,为获得/boot 空间,选择删除多余的内核文件 2.1 查询系统当前内核 ~$dpkg --get-selections |grep li ...

  4. [转载]iTOP-4418开发板Ubuntu系统烧写方法分享

    本文转自迅为论坛:http://topeetboard.com 开发平台:iTOP-4418开发板系统:Ubuntu 1. TF卡读写速度测试烧写 Ubuntu 对于 TF 卡的要求比较高,很多老旧的 ...

  5. Dynamic type checking and runtime type information

    动态类型的关键是将动态对象与实际类型信息绑定. See also: Dynamic programming language and Interpreted language Dynamic type ...

  6. vue动态加载组件

    vue动态加载组件,可以使用以下方式 <component :is="propertyname" v-for="tab in tabs"></ ...

  7. zabbix4.2学习笔记--用自带的mysql监控模块

    这里演示监控zabbix本身用到的mysql 第一步:建立mysql监控用户 在生产环境中,出于安全考虑,建议监控客户端数据库时,单独配置一个查询权限用户做查询操作即可 # 撤掉安装时给予的分配单个数 ...

  8. 笔试算法题(19):判断两条单向链表的公共节点 & 字符集删除函数

    出题:给定两个单向链表的头结点,判断其是否有公共节点并确定第一个公共节点的索引: 分析: 由于是单向链表,所以每个节点有且仅有一个后续节点,所以只可能是Y型交叉(每条链表中的某个节点同时指向一个公共节 ...

  9. [Python3网络爬虫开发实战] 1.4.2-MongoDB安装

    MongoDB是由C++语言编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,其内容存储形式类似JSON对象,它的字段值可以包含其他文档.数组及文档数组,非常灵活. MongoDB支持多 ...

  10. CentOS 6, 编译安装lamp (php-fpm)

    1 整体要求 php-fpm.httpd.mysql三者分别安装在三台虚拟机上: 第一台虚拟主机用于安装Mariadb,第二台虚拟主机安装php-fpm:第三台虚拟主机安装httpd.三台主机安装完之 ...