Protobuf协议测试利器之jmeter插件的开发实践
一、开发背景
Protobuf(全称为Google Protocol Buffer)是Google公司内部的混合语言数据标准,用于RPC系统和持续数据存储系统。Protobuf是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。
JMeter是Apache组织开发的基于Java的压力测试工具。它可以用于测试静态和动态资源,例如静态文件、Java小服务程序、CGI 脚本、Java 对象、数据库、FTP 服务器等等。JMeter也是前端或服务端接口测试中最常被选取使用的测试工具之一。
讯飞AI营销云平台的服务端经常需要测试protobuf协议类型的媒体广告请求。过去的方法(图1)是先使用JMeter构建测试计划,然后使用额外的Json转protobuf的工具构建需要的媒体广告请求,随后使用Linux服务器解密工具处理生成二进制文件,最后使用JMeter添加此二进制文件完成用例发送,从而实现一次想要的媒体广告请求到达服务端。在整个测试流程中,每发送一次测试用例需要经过两个JMeter软件之外的处理工作,无疑加大了测试人员的工作量。
图1 不使用插件的ADX协议测试流程
要减少测试人员发送测试用例的时间,考虑直接在JMeter中集成根据输入的Json自动生成protobuf请求的插件,是目前来看最有效的方法。经过插件工具的实际使用(图2)效果来看,我们在protobuf类型的媒体广告请求协议测试大约可减少测试人员70%的测试时间耗用。
图2 使用插件的ADX协议测试流程
二、插件开发方法与思路
在WEB测试领域中,JMeter是一个可以同时用于前端接口测试和服务端请求测试的开源工具,其插件的应用场景也非常广泛,插件的实现方式也很自由,只要遵守基本的JMeter插件规范,就可以实现很多需要的功能。
JMeter是一个纯JAVA的开源项目,因此所有的代码都可以从github上获取。此外github还有社区维护的jmeter-plugins项目,此项目包含了很多JMeter各种类型的插件源码,可以获取学习。由于使用JAVA编程语言开发,且代码资源丰富,因此JMeter的插件开发门槛不高。
JMeter含有非常多的组件,可以认为每一种组件都对应了一种插件的类型,因此开发插件时首先应该考虑的就是需要的插件类型。若所选取的插件有图形界面交互功能,还应该掌握一些Swing图形界面编程的方法。其次才是考虑插件功能的实现方法,这些可以参照jmeter-plugins开源项目中的编程方法。
前面已经提出将所有的JSON转protobuf文件的步骤以插件的形式集成到JMeter中。此处选取的插件类型为Sampler,此类型在JMeter中含有一个GUI。插件在JMeter中的基本工作流程为JMeter调用Sampler的GUI,然后GUI传递参数给实际实现功能的Sampler,最后Sampler将执行的结果返回给JMeter。
图3 插件执行过程
三、工程创建与二次开发
插件使用IDEA JAVA集成开发环境开发,使用Maven项目管理工具配置大部分需要的依赖包。
二次开发本插件时,需要提供对应的ADX或媒体协议的protobuf文件,以及是否使用BASE64加密和是否需要URL编码等参数。
1.打开工程项目文件夹
打开IDEA集成开发环境,选择“Open”打开项目文件夹。
图4 打开工程文件夹
2.添加JMeter依赖包
开发JMeter的插件,需要先在工程中引入JMeter插件基础Jar包,存放路径为JMeter安装目录/lib/ext/ApacheJMeter_core.jar
图5 打开Project Structure对话框
图6 选取项目依赖JAR包(一)
<center>图7 选取项目依赖JAR包(二)</center>
3.生成媒体协议类和json转换方法
根据媒体提供的proto类型的协议文件,以myMediaProtocol.proto为例创建JAVA类型媒体协议。
图8 媒体proto类型协议文件
使用proto命令编译生成MyMediaProtocol.java文件。此处应该使用2.6.0版本的proto进行编译。(不同的protobuf协议版本需要使用对应版本的proto程序编译,同时应该修改工程的pom.xml文件中引入的com.google.protobuf依赖包版本)具体的执行命令为protoc.exe -–java_out=./ .myMediaProtocol.proto
图9 编译生成JAVA类型媒体协议
按照以下方式编写json转protobuf的java方法。
图10 编写json转protobuf的方法
4.修改插件源码
新增媒体协议后,还需要在Sampler的GUI代码中,添加这一媒体协议的名称。在JComboBox中添加的字符串,会作为插件GUI的下拉框选项,以此区分传递给Sampler的媒体协议。
图11 在GUI下拉框中添加媒体协议
继续修改Sampler的代码,添加函数的名称。此处switch语句中的protoType变量存储着Sampler从Sampler GUI获取的下拉框选中的媒体协议。
图12 在Sampler中添加媒体协议的转换方法
5.编译和安装插件
点击build->Build Artifacts将插件编译成JAR包。
插件编译以后,将生成的JAR包复制到JMeter的安装路径/lib/ext/下完成插件安装,重启JMeter就可以使用了。
图13 编译插件JAR包
四、插件使用方法
新建测试计划,在HTTP的请求Sampler前面添加Json2Proto Sampler,最后添加查看结果树。JMeter会自上而下的运行各个组件,以此实现通过插件实现自动化测试媒体协议的功能。
图14 插件的使用方法
图15 插件返回结果分析
五、开发中遇到的问题
1.没有区分二进制文件与文本文件的区别导致发送媒体协议后服务器响应出错。
在一开始编码的时候,错误的直接使用FileWriter()类将转化后的protobuf类型的媒体协议写入到文件中,最终导致服务器响应出错。这个问题不易发现,原因是此方法产生的文件和正确的二进制媒体协议经过文本软件展示后结果非常相似,很难定位问题发生的原因。
解决方法是将原先json转化protobuf方法的返回结果继续转化为utf8编码的字符数组,再经过base64解密。最后调用FileOutputStream()类,此方法使用流直接生成二进制文件,可以得到正确的服务器响应结果。
2.错误理解JMeter Sampler类型插件的执行逻辑,导致插件不支持多线程操作。
一开始编写插件的时候没有考虑到多线程的操作,因此在没有正确理解JMeter的Sampler和SamplerGui两个类各个方法的情况下,将Sampler和SamplerGui的部分变量定为statis类型,进而导致JMeter多次调用插件时,多个Sampler和SamplerGui共享一组变量,出现逻辑错误。
解决方法是重新理解JMeter Sampler类型插件的执行逻辑,取消部分变量的statis属性和插件内GUI和Sampler的调用关系。