本文版权归xmeter.net 全部。欢迎转载,转载请注明出处。html
JMeter自己提供了插件机制,容许第三方扩展JMeter以支持JMeter不支持的协议的测试。本文以扩展一个简单的Apache Kafka producer sampler为例描述了如何对JMeter进行扩展,方便地实现对新协议的支持。java
Apache Kafka是由Apache软件基金会开发的一个开源消息系统项目。Kafka最初是由LinkedIn开发,并于2011年初开源。2012年10月从Apache孵化器毕业。该项目的目标是为处理实时数据提供一个统1、高通量、低等待的平台。git
以下图所示,Kafka的producer(数据生产者)经过Socket向Kafka集群上配置好的主题(topic)发送数据,consumer(数据消费者)在另一端消费由生产者那边产生的数据,并进行业务的处理。Kafka做为一个优秀的消息处理系统,在集群配置,主题管理等方面有不少须要深刻理解和优化等地方,本文的重点是JMeter的扩展,以Kafka的生产者为例来描述如何利用JMeter来模拟大量的生产者的调用,更多关于Kafka的细节请参考它的官方文档
github
扩展实现JMeter插件以前,须要先考虑清楚哪些选项须要暴露给测试人员。就像HTTP测试中,须要让用户输入服务器地址,端口号,路径等,同线程组里的链接是否共用等,若是提供是否共用链接这种选项的话,也须要在界面中体现,固然实现插件的时候处理链接的代码也会有所不一样。apache
往Kafka上发送消息的时候,须要提供一些基本配置信息(实际Kafka的生产者配置不止这些),若是读者对下面所说的内容不了解也没关系,只须要理解准备这些的目的是为了将这些配置信息提供给Kafka测试人员,在开始测试以前能够针对被测系统进行配置。服务器
下图是本文最终完成的JMeter Kafka插件的截图,测试开始以前须要输入上文所列的信息。网络
JMeter插件实现是标准的Java代码,打开Eclipse(做者使用的是4.5.2),新建一个Maven项目。咱们的项目中须要引用到JMeter自己提供的一些库,包括ApacheJMeter_core和ApacheJmeter_java,而且对JMeter的版本依赖是3.0。另外,还须要对Kafka的类库也须要引入,pom.xml中依赖部分的代码以下。并发
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <jmeter-version>3.0</jmeter-version> </properties> <dependencies> <dependency> <groupId>org.apache.jmeter</groupId> <artifactId>ApacheJMeter_core</artifactId> <version>${jmeter-version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.jmeter</groupId> <artifactId>ApacheJMeter_java</artifactId> <version>${jmeter-version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka_2.9.2</artifactId> <version>0.8.1.1</version> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
工程建立完毕以后,开始编写代码来实现插件。框架
JMeter的插件机制会在$JMETER_HOME/lib/ext目录下去动态加载符合指定条件的JAR包,并在JMeter中显示出来。好比要扩展UI的话,扩展的Java类的包名必须是”.gui.”,一样的扩展函数的Java类的包名必须是”.function.”.maven
新建一个类,org.apache.jmeter.protocol.kafka.control.gui.KafkaSamplerUI,并指定其父类为AbstractSamplerGui。该类须要实现如下的功能:
1)界面布局与控件。JMeter的界面是标准的Swing,因此里面的控件和布局都是标准的Swing写法。
2)界面与Sampler之间的数据交换。Sampler在JMeter中继承的是TestElement,用户输入的数据都是保存在Sampler中的,所以能够认为这个是界面的模型。界面与模型(Sampler)之间的数据交换须要实现父类的下面几个方法,
public void configure(TestElement el)
该方法用于把Sampler中的数据加载到界面中。在实现本身的逻辑以前,先调用一下父类的方法super.configure(el),这样能够确保框架自动为你加载一些缺省数据,好比Sampler的名字。
public void modifyTestElement(TestElement e)
这个方法用于把界面的数据移到Sampler中,恰好与上面的方法相反。在调用本身的实现方法以前,请先调用一下super.configureTestElement(e),这个会帮助移到一些缺省的数据。
public TestElement createTestElement()
该方法建立一个新的Sampler,而后将界面中的数据设置到这个新的Sampler实例中。
public void clearGui()
该方法会在reset新界面的时候调用,这里能够填入界面控件中须要显示的一些缺省的值。
在本文的实现中,分别实现上面的那些方法,包括显示5个控件(4个控制参数的控件在一个panel里,发送的消息的控件在另一个panel里),以及另外的几个方法用于和Sampler之间的数据交换等。完整的代码请参见这里。
新建一个Sampler,org.apache.jmeter.protocol.kafka.sampler.KafkaSampler,并指定其父类为AbstractSampler。该类须要实现如下的功能:
1)增长一些getter/setter方法,这些方法用于与UI之间的数据交换,这些数据在用户保存/打开脚本的时候将被自动序列化/反序列化。
2)实现sample方法:
public SampleResult sample(Entry entry)
该方法是JMeter实现对目标系统发起请求实际工做的地方。主要的工做是记录请求处理时间,对返回结果进行处理和判断,并根据处理结果返回SampleResult,该SampleResult中须要指定返回的内容是否成功,以及消息等。该方法的基本实现框架以下所示:
public SampleResult sample(Entry entry) { SampleResult result = new SampleResult(); result.setSampleLabel(getName()); try { result.sampleStart(); //对目标系统发出测试请求 result.sampleEnd(); result.setSuccessful(true); result.setResponseCodeOK(); } catch (Exception e) { result.sampleEnd(); // stop stopwatch result.setSuccessful(false); result.setResponseMessage("Exception: " + e); // get stack trace as a String to return as document data java.io.StringWriter stringWriter = new java.io.StringWriter(); e.printStackTrace(new java.io.PrintWriter(stringWriter)); result.setResponseData(stringWriter.toString(), null); result.setDataType(org.apache.jmeter.samplers.SampleResult.TEXT); result.setResponseCode("FAILED"); } return result; }
本文的实现中,生成一个Kafka的Producer对象,并将用户界面里指定的信息发送到Kafka服务器上。完整的代码请参见这里。
打包过程与普通的Maven项目类似,可是须要注意的是本插件须要把Kafka相关的依赖库文件也一并打入,不然还须要单独准备所依赖的JAR包。所以在pom.xml中加入下面的build插件。右击工程 》Run As 》Maven install,运行成功后,在工程的target目录下会生成一个kafka_jmeter-jar-with-dependencies.jar,这个就是咱们打好的插件。
<build> <finalName>${project.artifactId}</finalName> <defaultGoal>install</defaultGoal> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>assemble-all</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
插件开发完成后,将kafka_jmeter-jar-with-dependencies.jar拷贝到$JMETER_HOME/lib/ext目录下,若是以前已经打开了JMeter,则须要将JMeter关闭重启。
新建一个测试脚本,加入一个线程组,而后添加一个Sampler,若是运行正常,在子菜单中应该能看到咱们扩展出来的“Kafka Sampler”。
修改一下线程组里的线程数,则能实现多虚拟用户的并发测试了。下图是“查看结果树”里面显示的内容。
下图是Kafka的消费者端,能看到相关的消息已经发送成功。
如本文所示,若是经过比较“标准”的方式来扩展JMeter对新协议的测试,仍是有必定的工做量,特别是若是界面功能比较丰富的话,实现界面的那个类会比较复杂。若是对界面的要求不是很高,那么还有一种比较简单的可选项是经过扩展AbstractJavaSamplerClient,经过扩展该类,能够实现对简单的测试配置属性进行设置,并在runTest方法的实现中对目标系统发出请求
public SampleResult runTest(JavaSamplerContext context)
该方法的返回值是SampleResult,就是验证测试结果,与上文中实现步骤3比较相似。读者能够参见本文的参考资料中关于AbstractJavaSamplerClient中列出的几篇文章。
若是用户自定义的协议的测试,单台机器可以模拟的客户端是有限的,若是针对大规模的协议测试(好比本文举例的Kafka),可能须要准备大量的测试机器对被测系统进行打压,这个过程须要大量的准备机器环境,以及管理这些环境的工做,致使工做效率比较低、并且容易出错。XMeter将这些过程迁移至云端,弹性伸缩管理这些压力机,用户只要关注测试脚本的实现过程,而无需关心这些测试环境的管理,从而大大下降了大规模性能测试的复杂度。另外XMeter提供了丰富的测试报告,让性能问题一目了然。
JMeter扩展官方文档
AbstractJavaSamplerClient的方式扩展JMeter文章1
AbstractJavaSamplerClient的方式扩展JMeter文章2
AbstractJavaSamplerClient的方式扩展JMeter文章3
XMeter成立于2016年,核心团队都来自于IBM,是一家领先技术的性能测试持续集成咨询与服务提供商。咱们致力于提供给客户可靠,简单,低成本的性能测试解决方案。