根据需求,产品部分功能采用thrift-RPC协议进行接口的增、删、改、查,前期采用Junit对其进行测试,为了提高RPC接口测试的简洁化和后期的性能测试需求,打算通过Jmeter的java类测试实现。
前期准备:
开发提供了IDL描述的Thrift文件:dataService.thrift,其中定义了相关接口函数及数据类型,如下:
enum VStatus {
ON,
OFF
}
struct VData {
1: required string tablename;
2: required string time;
3: required string jsons;
4: optional VStatus status;
}
struct VCondition {
1: required string tablename;
2: required i64 starttime;
3: required i64 endtime;
}
service DataService {
string write(1: VData data);
string read(1: VCondition condition);
}
在本地部署thrift.exe并设置环境变量,之后在dataService.thrift所在的目录下执行:
<dependencies> <dependency> <groupId>org.apache.thriftgroupId> <artifactId>libthriftartifactId> <version>0.11.0version> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starterartifactId> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-testartifactId> dependency> <dependency> <groupId>org.apache.logging.log4jgroupId> <artifactId>log4j-apiartifactId> <version>2.8.2version> dependency> <dependency> <groupId>org.apache.logging.log4jgroupId> <artifactId>log4j-coreartifactId> <version>2.8.2version> dependency> dependencies>
之后手动加载本地Jmeter版本目录\Jmeter_Home\lib\ext中的ApacheJMeter_core.jar和ApacheJMeter_java.jar作为外部依赖包(注:直接maven加载相关版本的依赖包执行时存在冲突)
将之前生成的4个java文件导入项目,设置包名为:com.test.thrift.api,在项目包名下创建ReadRPC.java类,根据Jmeter中java类要求需要继承 AbstractJavaSamplerClient,代码如下:
package com.test.RPCTest; import com.test.thrift.api.DataService; import com.test.thrift.api.VCondition; import org.apache.jmeter.config.Arguments; import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient; import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext; import org.apache.jmeter.samplers.SampleResult; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; public class ReadRPC extends AbstractJavaSamplerClient{ private TTransport tTransport; private DataService.Client dataService; private TProtocol tProtocol; private VCondition vCondition; @Override public Arguments getDefaultParameters(){ //默认参数值,包括服务ip、端口、目标表、起止时间等 Arguments arguments=new Arguments(); arguments.addArgument("IP", "127.0.0.1"); arguments.addArgument("Port", "8888"); arguments.addArgument("TableName", "vle::test.trpc"); arguments.addArgument("StartTime", "1539752449"); arguments.addArgument("EndTime", "1539752449"); return arguments; } @Override public void setupTest(JavaSamplerContext context) { //初始化参数,并通过TTransport模式TBinaryProtocol二进制协议与服务端建立连接 // TODO Auto-generated method stub String ip=context.getParameter("IP"); int port=context.getIntParameter("Port"); String tableName=context.getParameter("TableName"); long startTime=context.getLongParameter("StartTime"); long endTime=context.getLongParameter("EndTime"); tTransport=new TSocket(ip,port,30000); vCondition=new VCondition(); try { tTransport.open(); tProtocol=new tBinaryProtocol(tTransport); dataService=new DataService.Client(tProtocol); vCondition.setTablename(tableName); vCondition.setStarttime(startTime); vCondition.setEndtime(endTime); } catch (Exception e) { // TODO: handle exception } super.setupTest(context); } @Override public SampleResult runTest(JavaSamplerContext context) { // TODO Auto-generated method stub SampleResult sampleResult = new SampleResult(); sampleResult.setDataEncoding("utf8"); sampleResult.sampleStart(); try { String msg=dataService.read(tCondition);//执行读操作,返回响应结果信息到msg if(null==msg){//为空判断 sampleResult.setSuccessful(false); sampleResult.setResponseMessage("响应结果为空!"); sampleResult.setSampleLabel("RPC读取"); sampleResult.setResponseOK(); sampleResult.setResponseData("响应结果为空!"); sampleResult.setDataType(SampleResult.TEXT); return sampleResult; } else { sampleResult.setSuccessful(true); sampleResult.setSampleLabel("RPC读取"); sampleResult.setResponseOK(); sampleResult.setResponseData(msg); System.out.println("msg="+msg); sampleResult.setDataType(SampleResult.TEXT); return sampleResult; } } catch (Exception e) { // TODO: handle exception sampleResult.setSuccessful(false); e.printStackTrace(); } finally{ sampleResult.sampleEnd(); } return sampleResult; } public void teardownTest(JavaSamplerContext context){ tTransport.close();//关闭连接 super.teardownTest(context); } }
在main函数中调用ReadRPC相关函数,代码如下:
public static void main( String[] args ) { JmeterRPC jrpc=new JmeterRPC(); jrpc.read(); } public void read(){ Arguments arguments=new Arguments(); arguments.addArgument("IP", "127.0.0.1"); arguments.addArgument("Port", "8888"); arguments.addArgument("TableName", "vle::test.trpc"); arguments.addArgument("StartTime", "1539752449"); arguments.addArgument("EndTime", "1539752449"); JavaSamplerContext context=new JavaSamplerContext(arguments); ReadRPC rpc=new ReadRPC(); rpc.setupTest(context); rpc.runTest(context); rpc.teardownTest(context); }
运行程序输出msg=[{".........相关响应数据.............."}]
调试成功后保存后,选中项目右键“Export”->“Java”->“Runnable JAR file”,点击“Next”,设置输出路径和依赖库,如下图所示:
备注:选择第一种方式将依赖包打在里面;
将打好的RPC.jar包拷贝到JMeter_Home\lib\ext下,启动jmeter控制台打印该jar信息,如下图所示:
启动完成后添加Java请求,显示读取类名,配置相关参数,如下图所示:
执行结果如下:
之后便可以通过该jar进行RPC相关接口测试,而且保证其他测试人员无需写代码便可进行测试。