JMeter 本身提供了插件机制,允许第三方扩展 JMeter 以支持 JMeter 不支持的协议的测试。本文以扩展一个简单的 Apache Kafka producer sampler 为例描述了如何对 JMeter 进行扩展,方便地实现对新协议的支持。
[Apache Kafka] 是由 Apache 软件基金会开发的一个开源消息系统项目。Kafka 最初是由 LinkedIn 开发,并于 2011 年初开源。2012 年 10 月从 Apache 孵化器毕业。该项目的目标是为处理实时数据提供一个统一、高通量、低等待的平台。
如下图所示,Kafka 的 producer(数据生产者)通过 Socket 向 Kafka 集群上配置好的主题(topic)发送数据,consumer(数据消费者)在另外一端消费由生产者那边产生的数据,并进行业务的处理。Kafka 作为一个优秀的消息处理系统,在集群配置,主题管理等方面有很多需要深入理解和优化等地方,本文的重点是 JMeter 的扩展,以 Kafka 的生产者为例来描述如何利用 JMeter 来模拟大量的生产者的调用,更多关于 Kafka 的细节请参考它的 [官方文档]
Kafka 生产、消费者模型
扩展实现 JMeter 插件之前,需要先考虑清楚哪些选项需要暴露给测试人员。就像 HTTP 测试中,需要让用户输入服务器地址,端口号,路径等,同线程组里的连接是否共用等,如果提供是否共用连接这种选项的话,也需要在界面中体现,当然实现插件的时候处理连接的代码也会有所不同。
往 Kafka 上发送消息的时候,需要提供一些基本配置信息(实际 Kafka 的生产者配置不止这些),如果读者对下面所说的内容不了解也不要紧,只需要理解准备这些的目的是为了将这些配置信息提供给 Kafka 测试人员,在开始测试之前可以针对被测系统进行配置。
下图是本文最终完成的 JMeter Kafka 插件的截图,测试开始之前需要输入上文所列的信息。
Kafka JMeter 插件截图
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. ”.
新建一个类,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 比较类似。
声明:看到过的好文章,转载分享,若有侵权,请及时联系,速删。