性能测试Jmeter压测ZooKeeper-自定义java请求

时间:2023-03-09 06:04:55
性能测试Jmeter压测ZooKeeper-自定义java请求

   要想通过自定义java请求来压测ZooKeeper,那么我们就需要做两件事情,第一我们需要知道java如何操作ZooKeeper,第二就是怎么能将我们写的jar包让jmeter识别,首先我们先来干第一件事。

一、java操作ZooKeeper

以下的代码是网上百度找到的,经过了一点点修改(对于测试其它的可以找其它的测试代码)

package com.comtop.ZookApi;

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper; /**
* Zookeeper base学习笔记
*/
public class ZookeeperBase { /** zookeeper地址 */
static final String CONNECT_ADDR = "10.10.3.136:32372";
/** session超时时间 */
static final int SESSION_OUTTIME = 2000;// ms
/** 信号量,阻塞程序执行,用于等待zookeeper连接成功,发送成功信号 */
static final CountDownLatch connectedSemaphore = new CountDownLatch(1); public static void main(String[] args) throws Exception { ZooKeeper zk = new ZooKeeper(CONNECT_ADDR, SESSION_OUTTIME,
new Watcher() {
public void process(WatchedEvent event) {
// 获取事件的状态
KeeperState keeperState = event.getState();
EventType eventType = event.getType();
// 如果是建立连接
if (KeeperState.SyncConnected == keeperState) {
if (EventType.None == eventType) {
// 如果建立连接成功,则发送信号量,让后续阻塞程序向下执行
System.out.println("zk 建立连接");
connectedSemaphore.countDown();
}
}
}
}); // 进行阻塞
connectedSemaphore.await(); System.out.println("..");
// 创建父节点
// zk.create("/testRoot", "testRoot".getBytes(), Ids.OPEN_ACL_UNSAFE,
// CreateMode.PERSISTENT); // 创建子节点
// zk.create("/testRoot/children", "children data".getBytes(),
// Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); // 获取节点洗信息
// byte[] data = zk.getData("/testRoot/children", false, null);
// System.out.println(new String(data));
// System.out.println(zk.getChildren("/testRoot", false));
// 修改节点的值
// zk.setData("/testRoot/children", "modify data root".getBytes(), -1);
// byte[] data = zk.getData("/testRoot/children", false, null);
// System.out.println(new String(data));
// 如果存在节点则删除节点
if (null != zk.exists("/testRoot/children", false)) {
// 删除节点
zk.delete("/testRoot/children", -1);
System.out.println(zk.exists("/testRoot/children", false));
}
zk.close(); } }

二、自定义java请求

一、环境准备
        1、新建一个java工程
        2、导入jar包:ApacheJMeter_core.jar     ApacheJMeter_java.jar    (该包在本地C:\apache-jmeter-3.0\lib\ext下,当然路径取决于本地环境)
                这两个jar是使用jmeter最基础的jar,能够让你的代码在jmeter中运行起来,如果在写代码的过程中需要其他的jar,自行导入。
二、写代码前该知道的
        1、如果想要让你的代码在jmeter中运行起来,在创建类的时候需要去继承AbstractJavaSamplerClient抽象类或者是实现JavaSamplerClient接口
            AbstractJavaSamplerClient抽象类是JavaSamplerClient接口的子类,当你不需要复写所有的需要复写的方法时,那么你只需要去继承AbstractJavaSamplerClient抽象类即可。
            如果你选择了实现JavaSamplerClient接口,那么你需要复写的方法有:
                         public SampleResult runTest(JavaSamplerContext context) {}
                         public void setupTest(JavaSamplerContext context) {}
                         public void teardownTest(JavaSamplerContext context) {}
                         public Arguments getDefaultParameters() {}
            这4个方法就必须要复写,但是如果选择继承AbstractJavaSamplerClient这个抽象类,那么只需要复写你需要的方法即可。
        2、方法说明:
                    public Arguments getDefaultParameters() {}
                            这个方法由Jmeter在进行添加javaRequest时第一个运行,它决定了你要在GUI中默认显示出哪些属性。
                    public void setupTest(JavaSamplerContext context) {}
                            这个方法相当于loadrunner中的init,我们可以用它来进行一些初始化的动作。
                    public SampleResult runTest(JavaSamplerContext context) {}
                            这个方法相当于loadrunner中的action,我们的核心测试代码就在这里了。
                    public void teardownTest(JavaSamplerContext context) {}
                            这个方法相当于loadrunner中的end,收尾的工作可以由它来做。
        3、除了以上2点,我们一般还需要去实现Serializable,序列化标记接口,这样可以让我们的类去实现序列化。
整体代码如下:
package com.comtop.ZkApiJM;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection; 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; import java.util.concurrent.CountDownLatch; import javax.management.RuntimeErrorException; import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper.States;
import org.apache.zookeeper.ZooKeeper; //public Arguments getDefaultParameters();设置可用参数及的默认值;
//public void setupTest(JavaSamplerContext arg0):每个线程测试前执行一次,做一些初始化工作;
//public SampleResult runTest(JavaSamplerContext arg0):开始测试,从arg0参数可以获得参数值;
//public void teardownTest(JavaSamplerContext arg0):测试结束时调用; public class ZkjavaRequest extends AbstractJavaSamplerClient implements Serializable { /** zookeeper地址 */
private String conn_addr; //存储用户输入的zk地址
// 测试用的数据
// private static String conn_addr1;
// private static String session_timeout1;
// private static String zk_father1;
// private static String zk_children1;
// private static String zk_context1;
// private static String resultData1; private static final String ConnAddrName="conn_addr" ; //设置GUI页面显示的变量名称
//设置GUI页面默认显示的变量值,默认值为空
private static final String ConnAddrValueDefault="10.10.3.136:32372"; /** session超时时间 */
private String session_timeout; //存储用户输入的session超时时间(单位ms) private static final String SessTimeName="session_timeout" ; //设置GUI页面显示的变量名称
//设置GUI页面默认显示的变量值,默认值为空
private static final String SessTimeValueDefault="5000"; //zk父节点
private String zk_father = "test"; //存储用户输入的zk父节点
private static final String ZkFatherName="zk_father" ; //设置GUI页面显示的变量名称
//设置GUI页面默认显示的变量值,默认值为空
private static final String ZkFatherValueDefault="/test"; /** 信号量,阻塞程序执行,用于等待zookeeper连接成功,发送成功信号 */
static final CountDownLatch connectedSemaphore = new CountDownLatch(1); //zk连接对象
private ZooKeeper zk; // resultData变量用来存储响应的数据,目的是显示到查看结果树中。
private String resultData; // 测试代码
// public static void main(String[] args) {
// haha();
// }
//
// public static void haha(){
// conn_addr1 = "10.10.3.136:32372";
// session_timeout1 = "2000";
// zk_father1 = "/test1";
// zk_children1 = "/test2";
// zk_context1 = "test2";
// try {
// ZooKeeper zk = new ZooKeeper(conn_addr1, Integer.valueOf(session_timeout1),
// new Watcher() {
// public void process(WatchedEvent event) {
// // 获取事件的状态
// KeeperState keeperState = event.getState();
// EventType eventType = event.getType();
// // 如果是建立连接
// if (KeeperState.SyncConnected == keeperState) {
// if (EventType.None == eventType) {
// // 如果建立连接成功,则发送信号量,让后续阻塞程序向下执行
// System.out.println("zk 建立连接");
// connectedSemaphore.countDown();
// }
// }
// }
// });
// connectedSemaphore.await();
// // 如果存在父节点则不创建父节点
// if (null == zk.exists(zk_father1, false)) {
// // 创建父节点
// zk.create(zk_father1, zk_father1.getBytes(), Ids.OPEN_ACL_UNSAFE,
// CreateMode.PERSISTENT);
// }
// // 创建子节点
// zk.create(zk_father1+zk_children1, zk_context1.getBytes(),
// Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// // 获取节点洗信息
// byte[] data = zk.getData(zk_father1+zk_children1, false, null);
// resultData1 = new String(data);
// System.out.println(new String(data));
// System.out.println(zk.getChildren("/testRoot", false));
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
//
//} /*
* 这个方法用来控制显示在GUI页面的属性,由用户来进行设置。
* 此方法不用调用,是一个与生命周期相关的方法,类加载则运行。
* (non-Javadoc)
* @see org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient#getDefaultParameters()
*/ @Override
public Arguments getDefaultParameters() {
System.out.println("读取属性值");
Arguments params = new Arguments();
params.addArgument("conn_addr",String.valueOf(ConnAddrValueDefault));
params.addArgument("session_timeout", String.valueOf(SessTimeValueDefault));
params.addArgument("zk_father", String.valueOf(ZkFatherValueDefault));
params.addArgument("zk_children","");
params.addArgument("zk_context","");
return params;
} /**
* 初始化方法,初始化性能测试时的每个线程
* 实际运行时每个线程仅执行一次,在测试方法运行前执行,类似于LoadRunner中的init方法
*/ @Override
public void setupTest(JavaSamplerContext jsc) {
conn_addr = jsc.getParameter(ConnAddrName, ConnAddrValueDefault);
session_timeout = jsc.getParameter(SessTimeName, SessTimeValueDefault);
zk_father = jsc.getParameter(ZkFatherName, ZkFatherValueDefault);
try {
zk = new ZooKeeper(conn_addr, Integer.valueOf(session_timeout),
new Watcher() {
public void process(WatchedEvent event) {
// 获取事件的状态
KeeperState keeperState = event.getState();
EventType eventType = event.getType();
// 如果是建立连接
if (KeeperState.SyncConnected == keeperState) {
if (EventType.None == eventType) {
// 如果建立连接成功,则发送信号量,让后续阻塞程序向下执行
System.out.println("zk 建立连接");
connectedSemaphore.countDown();
}
}
}
});
if (States.CONNECTING == zk.getState()) {
connectedSemaphore.await();
}
// 如果存在父节点则不创建父节点
if (null == zk.exists(zk_father, false)) {
// 创建父节点
zk.create(zk_father, zk_father.getBytes(), Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
} catch (Exception e) {
// TODO Auto-generated catch block
// e.printStackTrace();
throw new RuntimeException(e);
}
// 进行阻塞
// System.out.println(".."); } @Override
public SampleResult runTest(JavaSamplerContext arg0) {
String zk_children = arg0.getParameter("zk_children"); //获取zk_children
String zk_context = arg0.getParameter("zk_context"); //获取zk_context
// System.out.println(zk_context+" "+zk_children);
/*
* SampleResult这个类是用来将测试结果输出到查看结果树中的。
* 并且也是用来控制事务的开始和结束的。
*/ SampleResult results = new SampleResult();
results.setSampleLabel("zk节点测试:"+zk_father); try{
// 事务开始标记
results.sampleStart();
// 创建子节点
zk.create(zk_father+zk_children, zk_context.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 获取节点洗信息
byte[] data = zk.getData(zk_father+zk_children, false, null);
// System.out.println(new String(data));
resultData = new String(data);
if(null == resultData){
results.setSuccessful(false);
results.setResponseData("zk result is null",null);
results.setDataType(SampleResult.TEXT);
}
results.setSuccessful(true);
}catch(Exception e){
results.setSuccessful(false);
results.setResponseData(e.toString(),null);
results.setDataType(SampleResult.TEXT);
e.printStackTrace();
return results;
}finally{
//标记事务结束
results.sampleEnd();
}
// System.out.println("写入成功");
// results.setSuccessful(true);
results.setResponseData(resultData,null);//将数据打印到查看结果树当中
results.setDataType(SampleResult.TEXT);
return results;
} /**
* 测试结束方法,结束测试中的每个线程
* 实际运行时,每个线程仅执行一次,在测试方法运行结束后执行,类似于Loadrunner中的End方法
*/ public void teardownTest(JavaSamplerContext arg0) {
try {
zk.close();
System.out.println("关闭");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

代码及依赖包如下:

性能测试Jmeter压测ZooKeeper-自定义java请求