JMeter内置支持HTTP/HTTPS、FTP、JDBC、JMS、SOAP、TCP等一系列常用协议,可直接支持测试通过编写脚本实现相关协议的场景。除了这些协议之外,用户可能还需要测试一些其他的标准协议,或者在某些情况下,在标准协议中加入自定义的内容,需要测试自定义的协议。本文介绍的JavaSampler扩展机制是JMeter提供的一种方便实现对新协议支持的方式。JavaSampler简介JMeter中有一个重要的组件Sampler,即“sampler”。采样器包含上述一系列协议。可以认为“sampler”类别中的组件是对应协议的实现。但是,JavaSampler的含义并不意味着支持所谓的Java协议,也不能简单的称为Java采样器。更准确的意思是使用自定义Java类来扩展对新协议的支持。这些扩展的新协议通过“JavaRequest”添加到测试脚本中。下面两个图中的步骤显示了如何添加Java请求以及如何选择不同的JavaSampler。下面以MQTT协议中的连接为例,介绍使用JavaSampler进行扩展开发的具体步骤。准备开发环境在开发JMeter插件时,大多数情况下不需要下载JMeter的源代码,只需要引用相关的JMeter库即可。参见文章JMeterExtensionDevelopment:CustomFunctions准备开发环境。需要注意的是,在本文的例子中,除了引用了ApacheJMeter_core之外,还需要引入ApacheJMeter_core和一个支持MQTT协议的Java类库。在此示例中,使用了开源EclipsePahoJavaMQTT客户端库。其他MQTTJava类库当然也是可以的,这取决于被扩展的协议和协议扩展者的偏好。pom.xml中需要的依赖如下:org.eclipse.pahoorg.eclipse.paho.client.mqttv31.2。5org.apache.jmeterApacheJMeter_java5.4.3提供org.eclipse.pahoorg.eclipse.paho.client.mqttv31.2.5开发JavaSampler开发自己的JavaSampler包括以下步骤:继承JMeter抽象类org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient实现以下四个方法:方法一:SampleResultrunTest(JavaSamplerContextcontext)runTestmethod定义在接口JavaSamplerClient中,扩展协议的主要逻辑在该方法中编码实现,必须实现。方法二:publicArgumentsgetDefaultParameters()在getDefaultParameters方法中定义了随请求发送的默认参数,这些参数的名称和值会出现在JMeterJava请求对应的界面中。不必实施此方法。使用Java请求时,如果没有默认参数,也可以通过手动添加参数的方式添加。方法三:voidsetupTest(JavaSamplerContextcontext)方法四:voidteardownTest(JavaSamplerContextcontext)setupTest和teardownTest顾名思义就是Java请求开始时的初始化工作和结束时的扫尾工作。这两个方法不是必须要实现的。runTest方法首先关注runTest方法。runTest方法的返回结果是SampleResult,也就是每次“采样”的结果。方法实现的大致代码结构如下:@OverridepublicSampleResultrunTest(JavaSamplerContextcontext){SampleResultresult=newSampleResult();结果.sampleStart();try{//下面部分实现了具体的处理逻辑//...//具体结束业务逻辑//发送请求result.sampleEnd();//请求成功,设置测试结果为成功result.setSuccessful(true);result.setResponseData("数据...".getBytes());result.setResponseMessage("消息...");结果.setResponseCodeOK();}catch(Exceptione){//请求失败,设置测试结果为失败result.sampleEnd();结果.setSuccessful(false);结果.setResponseCode("500");}returnresult;}如上所示,代码逻辑主要是:1)必须向目标系统发送正确的协议数据。2)根据目标系统返回的数据,为SampleResult设置正确的方法、结束时间等,让JMeter引擎知道测试是否成功,并进一步正确显示在JMeter报告结果中.对于普通的MQTTTCP连接,业务逻辑部分的实现可以参考如下代码://MQTTBroker连接信息Stringbroker="tcp://broker.emqx.io:1883";Stringusername="emqx";Stringpassword="public";Stringclientid="publish_client";MqttClientclient=newMqttClient(broker,clientid,newMemoryPersistence());MqttConnectOptionsoptions=newMqttConnectOptions();options.setUserName(username);options.setPassword(password).toCharArray());client.connect(options);getDefaultParameters方法在上面的代码中,我们硬编码了MQTTBroker的连接信息,但是在实际应用场景中,我们希望通过一个JMeter插件来连接不同的MQTT代理。这种情况下,可以从JavaSamplerContext的参数中读取连接信息:);Stringclientid=context.getParameter("clientid");参数的具体值的输入由脚本编写者在JMeter界面编辑脚本时指定,或者在运行时使用指定变量的值。为了让脚本编写者更容易理解和更改所需的参数,我们通过getDefaultParameters方法将这些参数暴露在接口上:publicArgumentsgetDefaultParameters()arguments.addArgument("broker","tcp://broker.emqx.io:1883");arguments.addArgument("用户","emqx");arguments.addArgument("密码","公共");arguments.addArgument("clientid","publish_client"");returnarguments;}setupTest方法类似于编写JUnit测试的setup方法,这里主要针对单个虚拟用户进行一次初始化和准备操作。teardownTest方法类似于JUnit测试的teardown方法,这里主要针对单个虚拟用户进行收尾操作,需要注意的是,该方法的调用不是在单个虚拟用户的线程中,而是在所有虚拟用户在一个线程中依次执行方法编译、部署和使用代码写完之后,需要编译部署代码,pom.xml的构建设置和编译方法也可以参考上一篇JMeterExtensionDevelopment:CustomFunctions编译完成后会在target目录下生成一个jar包,注意通过samplepom.xml,编译出来的jar包中包含了需要的第三方类库,比如org.eclipse.paho.client.mqtt库,防止JMeter在跑题时发现第三方提供的类。将编译好的jar复制到$JMETER_HOME/lib/ext目录下,重启JMeter。启动完成后,添加一个Java请求,应该可以在类名下拉列表框中看到新扩展的类。如果不存在,请检查lib/ext目录下jar包是否复制正确,或者查看JMeter日志确认无异常。至此,我们通过JMeter提供的扩展机制完成了支持新协议的测试。可见JMeter对新协议的自定义扩展还是比较简单的。但是,JavaSampler扩展的协议与JMeter提供的标准协议相比,接口友好性仍然较差。我们将在本系列专题的后续文章中介绍如何使用JMeter更强大的扩展方式,敬请期待。版权声明:本文为EMQ原创,转载请注明出处。