要想通过自定义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(); } } }
代码及依赖包如下:
分类:
性能测试
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2018-01-09 安全测试5_服务端的安全漏洞(SQL注入、命令注入、文件操作类)