Jmeter测试工具实践:如何为Jmeter开发测试插件定制专属取样器?

JMeter原生支持多种不同的取样器(HTTP、TCP、JDBC、JMS等),每一种不同类型的取样器可以向服务器发送不同协议类型的请求。除了开箱即用的协议支持以外,JMeter还支持用户自己开发新协议的测试插件来进行扩展。

用户开发定制化的取样器插件,首先需要开发取样器的图形界面,扩展实现JMeter的AbstractSamplerGui类;然后开发取样器的处理逻辑类,扩展实现JMeter的AbstractSampler类,实现协议交互,发送请求报文并处理返回的响应结果;最后将开发调试好的代码编译,与描述了依赖关系的pom.xml一起打成JAR包,拷贝到JMeter的lib\ext目录下,其它相关依赖JAR包拷贝到JMeter的lib目录下。

重启JMeter后,选择用户开发好的定制化取样器测试插件,输入相关参数发起请求,即可执行扩展后的定制化测试插件支持的测试。下面详细说明一些具体定制化测试插件的设计思路和实现过程。

1、定制化的TCP取样器

定制化的TCP取样器(发送文本字符报文)

JMeter原生支持基于TCP协议的性能测试,提供了TCP取样器,通常情况下可以满足大多数基于TCP协议的测试需求。但在有些TCP协议的特定测试场景中无法完全满足实际的测试需求,比如服务器端返回的报文并没有一个明确的终止符(在TCP取样器中设定的“End of line(EOL) byte value”),而是返回一个定长的字节流报文,再比如要求发送的请求报文中含有中文,需要对请求报文进行特定的编码,JMeter原生TCP取样器需要在jmeter.properties文件中的tcp.charset属性设置具体值重启JMeter后生效,并不十分便捷,没有提供图形界面的tcp.charset参数设置项。

通过研读分析JMeter的源代码,开发实现定制化的TCP取样器插件,主要需要扩展实现org.apache.jmeter.config.gui.AbstractConfigGui抽象类、org.apache.jmeter.samplers.gui.AbstractSamplerGui抽象类创建定制化的TCP取样器界面,并且扩展实现org.apache.jmeter.samplers.AbstractSampler抽象类完成定制化的TCP取样器发送请求和接收响应信息的处理逻辑,最后扩展org.apache.jmeter.protocol.tcp.sampler.AbstractTCPClient类实现读取定长返回报文的处理逻辑。

扩展了AbstractConfigGui抽象类的具体类实现了定制化的TCP取样器配置界面。扩展了AbstractSamplerGui抽象类的具体类实现了定制化的TCP取样器界面。这两个GUI类都重写了图1中的前三个方法,实现了图1中的后三个方法。所设计的定制化取样器GUI的init方法实现详见图2。扩展了AbstractTCPClient类的TCPClientImpl2类中实现读取定长返回报文处理逻辑的read方法详见图3。

图1 GUI类需要实现的方法名

图2 init方法的实现

图3 read方法的实现

定制化的TCP取样器界面(见图4)在“End of line(EOL) byte value”之后添加了“Length of Receive”和“Charset”2个参数设置项。

如果“End of line(EOL) byte value”和“Length of Receive”同时设置的话,定制化的TCP取样器会优先使用“End of line(EOL) byte value”的设置值进行判断,“Length of Receive”的设置值会忽略。

如果只设置了“Length of Receive”,会返回指定长度的返回报文,如果指定的长度小于实际的字符流长度,超出指定长度的字符会被截掉。“Charset”设置值如果指定了具体的字符集,将按照指定的字符集编码发送请求报文,如果没有指定,按照操作系统默认字符集编码发送请求报文。

图4 定制化的TCP取样器界面(发送文本字符报文)

2、定制化的TCP取样器

定制化的TCP取样器(发送16进制字符报文)

在实际性能测试项目中,有时会遇到基于TCP协议的8583报文格式(银联基于ISO报文国际标准包格式的通讯协议,用于金融系统之间的报文交换,例如POS交易、ATM交易等)的测试场景。

在这样的测试场景下,JMeter的原生TCP取样器除了服务器返回报文长度判断问题以外,还存在由于返回的8583报文中可能存在多个3030,导致交易结果返回码(3030)校验判断不便的问题。

通过分析,开发实现定制化的TCP取样器(发送16进制字符报文)插件,除了实现AbstractConfigGui抽象类和AbstractSamplerGui抽象类创建定制化的TCP取样器(发送16进制字符报文)界面之外,还需要在扩展实现AbstractSampler抽象类中实现自动校验指定位返回报文内容判断的处理逻辑(见图5)。

图5 setupSampleResult2方法的实现

定制化的TCP取样器(发送16进制字符报文)界面(见图6)在“End of line(EOL) byte value”之后除了添加“Length of Receive”参数设置项以外,增加了“Auto Assertion”勾选项、“StartPosition”和“FindValue”参数设置项。

如果勾选了“Auto Assertion”自动校验选项,并设置了“StartPosition”和“FindValue”参数,不用手工添加新的响应断言就可以自动对返回报文指定起始位的返回码进行校验判断,判断返回码是否与预期一致,一致的话交易成功,否则交易失败。

图6 定制化的TCP取样器界面(发送16进制字符报文)

3、定制化的SSH取样器和SFTP取样器

测试人员在实际性能测试过程中,经常会登录到远程Linux服务器上进行一系列的操作(例如执行nmon命令,下载nmon监控结果文件等)。有些nmon操作命令基本上是固定的,但每次登录到服务器上重复操作会显得较为繁琐。尤其是当监控的服务器数量较多时,这些重复操作就显得十分费时。

开发定制化的SSH取样器插件和SFTP取样器插件,利用JMeter支持并发发送请求,编写一个JMeter自动化监控脚本,用来代替手工执行nmon命令可以很大程度上提高监控操作效率。

开发实现定制化的SSH取样器插件和SFTP取样器插件,除了实现AbstractConfigGui抽象类和AbstractSamplerGui抽象类创建定制化的SSH取样器界面和SFTP取样器界面之外,还需要扩展实现AbstractSampler抽象类负责命令执行的处理逻辑,而处理逻辑的实现依赖于Jsch。

Jsch是一种支持SSH2协议的纯Java实现,可以满足通过SSH2协议连接到服务器并执行命令,进而执行文件传输和文件下载。实现了SSH取样器处理逻辑的类中编写了doCommand方法(见图7)负责处理命令操作。实现了SFTP取样器处理逻辑的类中编写了doFileTransfer方法(见图8)负责处理文件上传下载操作。

图7 doCommand方法的实现

图8 doFileTransfer方法的实现

开发实现了定制化的SSH取样器和SFTP取样器之后,可以编写一个JMeter自动化监控脚本来代替手工执行nmon命令操作。执行JMeter脚本就可以自动实现在设置的监控时段一次性的将多个服务器的nmon监控结果文件下载到本地。

在这个JMeter脚本中,配置项在用户定义变量中设置(见图9),将监控的服务器地址、操作系统用户、密码,以及nmon文件目录等参数值放到参数文件中,通过CSV数据文件设置定义变量(见图10),将对应的nmon命令通过SSH取样器(见图11)执行,对应的下载操作通过SFTP取样器(见图11)执行。

图9 用户定义变量的设置

图10 CSV数据文件设置

图11 SSH取样器界面和SFTP取样器界面

4、总结

当前,上述基于JMeter开发的定制化测试插件已经在实际性能测试项目中实践应用,解决了一些特定场景下的测试需求。随着JMeter在性能测试工作中的广泛应用,针对一些特色测试场景和特定测试需求,测试人员可以扩展开发自己的测试插件并在一定范围内共享使用,更好的提高性能测试工作效率。