性能工具之Jmeter压测Thrift RPC服务

概述

Thrift是一个可互操作和可伸缩服务的框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 等等编程语言间无缝结合的、高效的服务。

Thrift最初由facebook开发,07年四月开放源码,08年5月进入apache孵化器。thrift允许你定义一个简单的定义文件中的数据类型和服务接口(IDL)。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。

其传输数据采用二进制格式,相对于XML和JSON等序列化方式体积更小,对于高并发、大数据量和多语言的环境更有优势。 Thrift它含有三个主要的组件:protocol,transport和server,其中,protocol定义了消息是怎样序列化的,transport定义了消息是怎样在客户端和服务器端之间通信的,server用于从transport接收序列化的消息,根据protocol反序列化之,调用用户定义的消息处理器,并序列化消息处理器的响应,然后再将它们写回transport。

官网地址:thrift.apache.org

基本概念

架构图

性能工具之Jmeter压测Thrift RPC服务

堆栈的顶部是从Thrift定义文件生成的代码。Thrift 服务生成的客户端和处理器代码。这些由图中的棕色框表示。红色框为发送的数据结构(内置类型除外)也会生成代码。协议和传输是Thrift运行时库的一部分。因此使用Thrift可以定义服务,并且可以*更改协议和传输,而无需重新生成代码。 Thrift还包括一个服务器基础结构,用于将协议和传输绑定在一起。有可用的阻塞,非阻塞,单线程和多线程服务器。 堆栈的“底层I / O”部分根据所开发语言而有所不同。对于Java和Python网络I / O,Thrift库利用内置库,而C ++实现使用自己的自定义实现。

数据类型:

基本类型:

  • bool:布尔值,true 或 false,对应 Java 的 boolean

  • byte:8 位有符号整数,对应 Java 的 byte

  • i16:16 位有符号整数,对应 Java 的 short

  • i32:32 位有符号整数,对应 Java 的 int

  • i64:64 位有符号整数,对应 Java 的 long

  • double:64 位浮点数,对应 Java 的 double

  • string:未知编码文本或二进制字符串,对应 Java 的 String

结构体类型:

  • struct:定义公共的对象,类似于 C 语言中的结构体定义,在 Java 中是一个 JavaBean

集合类型:

  • list:对应 Java 的 ArrayList

  • set:对应 Java 的 HashSet

  • map:对应 Java 的 HashMap

异常类型:

  • exception:对应 Java 的 Exception

服务类型:

  • service:对应服务的类

数据传输层Transport

  • TSocket —— 使用阻塞式 I/O 进行传输,是最常见的模式

  • TFramedTransport —— 使用非阻塞方式,按块的大小进行传输,类似于 Java 中的 NIO,若使用 TFramedTransport 传输层,其服务器必须修改为非阻塞的服务类型

  • TNonblockingTransport —— 使用非阻塞方式,用于构建异步客户端

数据传输协议Protocol

Thrift 可以让用户选择客户端与服务端之间传输通信协议的类别,在传输协议上总体划分为文本 (text) 和二进制 (binary) 传输协议,为节约带宽,提高传输效率,一般情况下使用二进制类型的传输协议为多数,有时还会使用基于文本类型的协议,这需要根据项目 / 产品中的实际需求。

常用协议有以下几种:

  • TBinaryProtocol : 二进制格式.

  • TCompactProtocol : 高效率的、密集的二进制压缩格式

  • TJSONProtocol : JSON格式

  • TSimpleJSONProtocol : 提供JSON只写协议, 生成的文件很容易通过脚本语言解析

注意:客户端和服务端的协议要一致。

服务器类型Server

  • TSimpleServer ——单线程服务器端使用标准的阻塞式 I/O,一般用于测试。

  • TThreadPoolServer —— 多线程服务器端使用标准的阻塞式 I/O,预先创建一组线程处理请求。

  • TNonblockingServer —— 多线程服务器端使用非阻塞式 I/O,服务端和客户端需要指定 TFramedTransport 数据传输的方式。

  • THsHaServer —— 半同步半异步的服务端模型,需要指定为: TFramedTransport 数据传输的方式。它使用一个单独的线程来处理网络I/O,一个独立的worker线程池来处理消息。这样,只要有空闲的worker线程,消息就会被立即处理,因此多条消息能被并行处理。

  • TThreadedSelectorServer —— TThreadedSelectorServer允许你用多个线程来处理网络I/O。它维护了两个线程池,一个用来处理网络I/O,另一个用来进行请求的处理。当网络I/O是瓶颈的时候,TThreadedSelectorServer比THsHaServer的表现要好。

实现逻辑

服务端

实现服务处理接口?impl

创建TProcessor 创建TServerTransport 创建TProtocol 创建TServer 启动Server

客户端

创建Transport 创建TProtocol 基于TTransport和TProtocol创建 Client 调用Client的相应方法

ThriftServerDemo实例

新建?Maven项目,并且添加?thrift依赖包

  1. ?<dependencies>

  2. ? ? ? ?<dependency>

  3. ? ? ? ? ? ?<groupId>org.apache.thrift</groupId>

  4. ? ? ? ? ? ?<artifactId>libthrift</artifactId>

  5. ? ? ? ? ? ?<version>0.9.3</version>

  6. ? ? ? ?</dependency>

  7. ? ? ? ?<dependency>

  8. ? ? ? ? ? ?<groupId>org.slf4j</groupId>

  9. ? ? ? ? ? ?<artifactId>slf4j-log4j12</artifactId>

  10. ? ? ? ? ? ?<version>1.7.12</version>

  11. ? ? ? ?</dependency>

  12. ? ? ? ?<dependency>

  13. ? ? ? ? ? ?<groupId>org.apache.logging.log4j</groupId>

  14. ? ? ? ? ? ?<artifactId>log4j-api</artifactId>

  15. ? ? ? ? ? ?<version>2.7</version>

  16. ? ? ? ?</dependency>

  17. ? ? ? ?<dependency>

  18. ? ? ? ? ? ?<groupId>org.apache.logging.log4j</groupId>

  19. ? ? ? ? ? ?<artifactId>log4j-core</artifactId>

  20. ? ? ? ? ? ?<version>2.7</version>

  21. ? ? ? ?</dependency>

  22. ? ?</dependencies>

  23. ? ?<build>

  24. ? ? ? ?<plugins>

  25. ? ? ? ? ? ?<plugin>

  26. ? ? ? ? ? ? ? ?<groupId>org.apache.maven.plugins</groupId>

  27. ? ? ? ? ? ? ? ?<artifactId>maven-compiler-plugin</artifactId>

  28. ? ? ? ? ? ? ? ?<version>3.3</version>

  29. ? ? ? ? ? ? ? ?<configuration>

  30. ? ? ? ? ? ? ? ? ? ?<source>1.8</source>

  31. ? ? ? ? ? ? ? ? ? ?<target>1.8</target>

  32. ? ? ? ? ? ? ? ? ? ?<encoding>utf-8</encoding>

  33. ? ? ? ? ? ? ? ?</configuration>

  34. ? ? ? ? ? ?</plugin>

  35. ? ? ? ?</plugins>

  36. ? ?</build>


编写?IDL接口并生成接口文件

  1. namespace java thrift.service

  2. // 计算类型 - 仅限整数四则运算

  3. enum ComputeType {

  4. ? ?ADD = 0;

  5. ? ?SUB = 1;

  6. ? ?MUL = 2;

  7. ? ?DIV = 3;

  8. }

  9. // 服务请求

  10. struct ComputeRequest {

  11. ? ?1:required i64 x;

  12. ? ?2:required i64 y;

  13. ? ?3:required ComputeType computeType;

  14. }

  15. // 服务响应

  16. struct ComputeResponse {

  17. ? ?1:required i32 errorNo;

  18. ? ?2:optional string errorMsg;

  19. ? ?3:required i64 computeRet;

  20. }

  21. service ComputeServer {

  22. ? ?ComputeResponse getComputeResult(1:ComputeRequest request);

  23. }


执行编译命令:

  1. thrift-0.11.0.exe -r -gen java computeServer.thrift

拷贝生成的?Service类文件到?IDEA?

性能工具之Jmeter压测Thrift RPC服务

服务端接口实现

  1. public class ThriftTestImpl implements ComputeServer.Iface {

  2. ? ?private static final Logger logger = LogManager.getLogger(ThriftTestImpl.class);

  3. ? ?public ComputeResponse getComputeResult(ComputeRequest request) {

  4. ? ? ? ?ComputeType computeType = request.getComputeType();

  5. ? ? ? ?long x = request.getX();

  6. ? ? ? ?long y = request.getY();

  7. ? ? ? ?logger.info("get compute result begin. [x:{}] [y:{}] [type:{}]", x, y, computeType.toString());

  8. ? ? ? ?long begin = System.currentTimeMillis();

  9. ? ? ? ?ComputeResponse response = new ComputeResponse();

  10. ? ? ? ?response.setErrorNo(0);

  11. ? ? ? ?try {

  12. ? ? ? ? ? ?long ret;

  13. ? ? ? ? ? ?if (computeType == ComputeType.ADD) {

  14. ? ? ? ? ? ? ? ?ret = add(x, y);

  15. ? ? ? ? ? ? ? ?response.setComputeRet(ret);

  16. ? ? ? ? ? ?} else if (computeType == ComputeType.SUB) {

  17. ? ? ? ? ? ? ? ?ret = sub(x, y);

  18. ? ? ? ? ? ? ? ?response.setComputeRet(ret);

  19. ? ? ? ? ? ?} else if (computeType == ComputeType.MUL) {

  20. ? ? ? ? ? ? ? ?ret = mul(x, y);

  21. ? ? ? ? ? ? ? ?response.setComputeRet(ret);

  22. ? ? ? ? ? ?} else {

  23. ? ? ? ? ? ? ? ?ret = div(x, y);

  24. ? ? ? ? ? ? ? ?response.setComputeRet(ret);

  25. ? ? ? ? ? ?}

  26. ? ? ? ?} catch (Exception e) {

  27. ? ? ? ? ? ?response.setErrorNo(1001);

  28. ? ? ? ? ? ?response.setErrorMsg(e.getMessage());

  29. ? ? ? ? ? ?logger.error("exception:", e);

  30. ? ? ? ?}

  31. ? ? ? ?long end = System.currentTimeMillis();

  32. ? ? ? ?logger.info("get compute result end. [errno:{}] cost:[{}ms]", response.getErrorNo(), (end - begin));

  33. ? ? ? ?return response;

  34. ? ?}

  35. ? ?private long add(long x, long y) {

  36. ? ? ? ?return x + y;

  37. ? ?}

  38. ? ?private long sub(long x, long y) {

  39. ? ? ? ?return x - y;

  40. ? ?}

  41. ? ?private long mul(long x, long y) {

  42. ? ? ? ?return x * y;

  43. ? ?}

  44. ? ?private long div(long x, long y) {

  45. ? ? ? ?return x / y;

  46. ? ?}

  47. }


服务端实现

  1. public class ServerMain {

  2. ? ?private static final Logger logger = LogManager.getLogger(ServerMain.class);

  3. ? ?public static void main(String[] args) {

  4. ? ? ? ?try {

  5. ? ? ? ? ? ?//实现服务处理接口impl

  6. ? ? ? ? ? ?ThriftTestImpl workImpl = new ThriftTestImpl();

  7. ? ? ? ? ? ?//创建TProcessor

  8. ? ? ? ? ? ?TProcessor tProcessor = new ComputeServer.Processor<ComputeServer.Iface>(workImpl);

  9. ? ? ? ? ? ?//创建TServerTransport,非阻塞式 I/O,服务端和客户端需要指定 TFramedTransport 数据传输的方式

  10. ? ? ? ? ? ?final TNonblockingServerTransport transport = new TNonblockingServerSocket(9999);

  11. ? ? ? ? ? ?//创建TProtocol

  12. ? ? ? ? ? ?TThreadedSelectorServer.Args ttpsArgs = new TThreadedSelectorServer.Args(transport);

  13. ? ? ? ? ? ?ttpsArgs.transportFactory(new TFramedTransport.Factory());

  14. ? ? ? ? ? ?//二进制格式反序列化

  15. ? ? ? ? ? ?ttpsArgs.protocolFactory(new TBinaryProtocol.Factory());

  16. ? ? ? ? ? ?ttpsArgs.processor(tProcessor);

  17. ? ? ? ? ? ?ttpsArgs.selectorThreads(16);

  18. ? ? ? ? ? ?ttpsArgs.workerThreads(32);

  19. ? ? ? ? ? ?logger.info("compute service server on port :" + 9999);

  20. ? ? ? ? ? ?//创建TServer

  21. ? ? ? ? ? ?TServer server = new TThreadedSelectorServer(ttpsArgs);

  22. ? ? ? ? ? ?//启动Server

  23. ? ? ? ? ? ?server.serve();

  24. ? ? ? ?} catch (Exception e) {

  25. ? ? ? ? ? ?logger.error(e);

  26. ? ? ? ?}

  27. ? ?}

  28. }


服务端整体代码结构?

性能工具之Jmeter压测Thrift RPC服务

log4j2.xml配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->

  3. <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->

  4. <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->

  5. <configuration status="INFO" monitorInterval="30">

  6. ? ?<!--先定义所有的appender-->

  7. ? ?<appenders>

  8. ? ? ? ?<!--这个输出控制台的配置-->

  9. ? ? ? ?<console name="Console" target="SYSTEM_OUT">

  10. ? ? ? ? ? ?<!--输出日志的格式-->

  11. ? ? ? ? ? ?<PatternLayout pattern="%highlight{[ %p ] [%-d{yyyy-MM-dd HH:mm:ss}] [%l] %m%n}"/>

  12. ? ? ? ?</console>

  13. ? ? ? ?<RollingFile name="RollingFileInfo" fileName="log/log.log" filePattern="log/log.log.%d{yyyy-MM-dd}">

  14. ? ? ? ? ? ?<!-- 只接受level=INFO以上的日志 -->

  15. ? ? ? ? ? ?<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>

  16. ? ? ? ? ? ?<PatternLayout pattern="[ %p ] [%-d{yyyy-MM-dd HH:mm:ss}] [ LOGID:%X{logid} ] [%l] %m%n"/>

  17. ? ? ? ? ? ?<Policies>

  18. ? ? ? ? ? ? ? ?<TimeBasedTriggeringPolicy modulate="true" interval="1"/>

  19. ? ? ? ? ? ? ? ?<SizeBasedTriggeringPolicy/>

  20. ? ? ? ? ? ?</Policies>

  21. ? ? ? ?</RollingFile>

  22. ? ? ? ?<RollingFile name="RollingFileError" fileName="log/error.log" filePattern="log/error.log.%d{yyyy-MM-dd}">

  23. ? ? ? ? ? ?<!-- 只接受level=WARN以上的日志 -->

  24. ? ? ? ? ? ?<Filters>

  25. ? ? ? ? ? ? ? ?<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY" />

  26. ? ? ? ? ? ?</Filters>

  27. ? ? ? ? ? ?<PatternLayout pattern="[ %p ] %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] [%l] %m%n"/>

  28. ? ? ? ? ? ?<Policies>

  29. ? ? ? ? ? ? ? ?<TimeBasedTriggeringPolicy modulate="true" interval="1"/>

  30. ? ? ? ? ? ? ? ?<SizeBasedTriggeringPolicy/>

  31. ? ? ? ? ? ?</Policies>

  32. ? ? ? ?</RollingFile>

  33. ? ?</appenders>

  34. ? ?<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->

  35. ? ?<loggers>

  36. ? ? ? ?<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->

  37. ? ? ? ?<logger name="org.springframework" level="INFO"></logger>

  38. ? ? ? ?<logger name="org.mybatis" level="INFO"></logger>

  39. ? ? ? ?<root level="all">

  40. ? ? ? ? ? ?<appender-ref ref="Console"/>

  41. ? ? ? ? ? ?<appender-ref ref="RollingFileInfo"/>

  42. ? ? ? ? ? ?<appender-ref ref="RollingFileError"/>

  43. ? ? ? ?</root>

  44. ? ?</loggers>

  45. </configuration>


Jmeter测试类编写

利用JMeter调用Java测试类去调用对应的后台服务,并记住每次调用并获取反馈值的RT,ERR%,只需要按照单线程的方式去实现测试业务,也无需添加各种埋点收集数据?

?

新建一个?JavaMaven工程,添加?JMeter及?thrift依赖包

  1. <dependencies>

  2. ? ? ? ?<dependency>

  3. ? ? ? ? ? ?<groupId>org.apache.jmeter</groupId>

  4. ? ? ? ? ? ?<artifactId>ApacheJMeter_core</artifactId>

  5. ? ? ? ? ? ?<version>4.0</version>

  6. ? ? ? ?</dependency>

  7. ? ? ? ?<dependency>

  8. ? ? ? ? ? ?<groupId>org.apache.jmeter</groupId>

  9. ? ? ? ? ? ?<artifactId>ApacheJMeter_java</artifactId>

  10. ? ? ? ? ? ?<version>4.0</version>

  11. ? ? ? ?</dependency>

  12. ? ? ? ?<dependency>

  13. ? ? ? ? ? ?<groupId>org.apache.thrift</groupId>

  14. ? ? ? ? ? ?<artifactId>libthrift</artifactId>

  15. ? ? ? ? ? ?<version>0.11.0</version>

  16. ? ? ? ?</dependency>

  17. ? ? ? ?<dependency>

  18. ? ? ? ? ? ?<groupId>org.apache.logging.log4j</groupId>

  19. ? ? ? ? ? ?<artifactId>log4j-api</artifactId>

  20. ? ? ? ? ? ?<version>2.11.1</version>

  21. ? ? ? ?</dependency>

  22. ? ? ? ?<dependency>

  23. ? ? ? ? ? ?<groupId>org.apache.logging.log4j</groupId>

  24. ? ? ? ? ? ?<artifactId>log4j-core</artifactId>

  25. ? ? ? ? ? ?<version>2.11.1</version>

  26. ? ? ? ?</dependency>

  27. ? ? ? ?<dependency>

  28. ? ? ? ? ? ?<groupId>org.slf4j</groupId>

  29. ? ? ? ? ? ?<artifactId>slf4j-log4j12</artifactId>

  30. ? ? ? ? ? ?<version>1.7.25</version>

  31. ? ? ? ?</dependency>

  32. ? ?</dependencies>

  33. ? ?<build>

  34. ? ? ? ?<plugins>

  35. ? ? ? ? ? ?<plugin>

  36. ? ? ? ? ? ? ? ?<groupId>org.apache.maven.plugins</groupId>

  37. ? ? ? ? ? ? ? ?<artifactId>maven-compiler-plugin</artifactId>

  38. ? ? ? ? ? ? ? ?<version>3.7.0</version>

  39. ? ? ? ? ? ? ? ?<configuration>

  40. ? ? ? ? ? ? ? ? ? ?<source>1.8</source>

  41. ? ? ? ? ? ? ? ? ? ?<target>1.8</target>

  42. ? ? ? ? ? ? ? ? ? ?<encoding>utf-8</encoding>

  43. ? ? ? ? ? ? ? ?</configuration>

  44. ? ? ? ? ? ?</plugin>

  45. ? ? ? ?</plugins>

  46. ? ?</build>


ThriftClient测试类编写

  1. public class ThriftClient {

  2. ? ?private ComputeServer.Client client = null;

  3. ? ?private TTransport tTransport = null;

  4. ? ?public ThriftClient(String ip,int port){

  5. ? ? ? ?try {

  6. ? ? ? ? ? ?TTransport tTransport = new TFramedTransport(new TSocket(ip,port));

  7. ? ? ? ? ? ?tTransport.open();

  8. ? ? ? ? ? ?TProtocol tProtocol = new TBinaryProtocol(tTransport);

  9. ? ? ? ? ? ?client = new ComputeServer.Client(tProtocol);

  10. ? ? ? ?} catch (TTransportException e) {

  11. ? ? ? ? ? ?e.printStackTrace();

  12. ? ? ? ?}

  13. ? ?}

  14. ? ?public ComputeResponse getResponse(ComputeRequest request){

  15. ? ? ? ?try {

  16. ? ? ? ? ? ?ComputeResponse response = client.getComputeResult(request);

  17. ? ? ? ? ? ?return response;

  18. ? ? ? ?} catch (TException e) {

  19. ? ? ? ? ? ?e.printStackTrace();

  20. ? ? ? ? ? ?return null;

  21. ? ? ? ?}

  22. ? ?}

  23. ? ?public void ?close(){

  24. ? ? ? ?if (tTransport != null && tTransport.isOpen()){

  25. ? ? ? ? ? ?tTransport.close();

  26. ? ? ? ?}

  27. ? ?}

  28. }


注意:需要把编写?IDL接口文件拷贝到工程里

新建一个?JavaClass,如下例中的?TestThriftByJmeter,并继承?AbstractJavaSamplerClient。?AbstractJavaSamplerClient中默认实现了四个可以覆盖的方法,分别是?getDefaultParameters(),?setupTest(),?runTest()和?teardownTest()方法。

  • getDefaultParameters?方法主要用于设置传入界面的参数;

  • setupTest方法为初始化方法,用于初始化性能测试时的每个线程;

  • runTest方法为性能测试时的线程运行体;

  • teardownTest方法为测试结束方法,用于结束性能测试中的每个线程。

编写TestThriftByJmeter测试类

  1. public class TestThriftByJmeter extends AbstractJavaSamplerClient {

  2. ? ?private ThriftClient client;

  3. ? ?private ComputeRequest request;

  4. ? ?private ComputeResponse response;

  5. ? ?//设置传入界面的参数

  6. ? ?@Override

  7. ? ?public Arguments getDefaultParameters(){

  8. ? ? ? ?Arguments arguments = new Arguments();

  9. ? ? ? ?arguments.addArgument("ip","172.16.14.251");

  10. ? ? ? ?arguments.addArgument("port","9999");

  11. ? ? ? ?arguments.addArgument("X","0");

  12. ? ? ? ?arguments.addArgument("Y","0");

  13. ? ? ? ?arguments.addArgument("type","0");

  14. ? ? ? ?return arguments;

  15. ? ?}

  16. ? ?//初始化方法

  17. ? ?@Override

  18. ? ?public void setupTest(JavaSamplerContext context){

  19. ? ? ? ?//获取Jmeter中设置的参数

  20. ? ? ? ?String ip = context.getParameter("ip");

  21. ? ? ? ?int port = context.getIntParameter("port");

  22. ? ? ? ?int x = context.getIntParameter("X");

  23. ? ? ? ?int y = context.getIntParameter("Y");

  24. ? ? ? ?ComputeType type = ComputeType.findByValue(context.getIntParameter("type"));

  25. ? ? ? ?//创建客户端

  26. ? ? ? ?client = new ThriftClient(ip,port);

  27. ? ? ? ?//设置request请求

  28. ? ? ? ?request = new ComputeRequest(x,y,type);

  29. ? ? ? ?super.setupTest(context);

  30. ? ?}

  31. ? ?//性能测试线程运行体

  32. ? ?@Override

  33. ? ?public SampleResult runTest(JavaSamplerContext context) {

  34. ? ? ? ?SampleResult result = new SampleResult();

  35. ? ? ? ?//开始统计响应时间标记

  36. ? ? ? ?result.sampleStart();

  37. ? ? ? ?try {

  38. ? ? ? ? ? ?long begin = System.currentTimeMillis();

  39. ? ? ? ? ? ?response = client.getResponse(request);

  40. ? ? ? ? ? ?long cost = (System.currentTimeMillis() - begin);

  41. ? ? ? ? ? ?//打印时间戳差值。Java请求响应时间

  42. ? ? ? ? ? ?System.out.println(response.toString()+" 总计花费:["+cost+"ms]");

  43. ? ? ? ? ? ?if (response == null){

  44. ? ? ? ? ? ? ? ?//设置测试结果为fasle

  45. ? ? ? ? ? ? ? ?result.setSuccessful(false);

  46. ? ? ? ? ? ? ? ?return result;

  47. ? ? ? ? ? ?}

  48. ? ? ? ? ? ?if (response.getErrorNo() == 0){

  49. ? ? ? ? ? ? ? ?//设置测试结果为true

  50. ? ? ? ? ? ? ? ?result.setSuccessful(true);

  51. ? ? ? ? ? ?}else{

  52. ? ? ? ? ? ? ? ?result.setSuccessful(false);

  53. ? ? ? ? ? ? ? ?result.setResponseMessage("ERROR");

  54. ? ? ? ? ? ?}

  55. ? ? ? ?}catch (Exception e){

  56. ? ? ? ? ? ?result.setSuccessful(false);

  57. ? ? ? ? ? ?result.setResponseMessage("ERROR");

  58. ? ? ? ? ? ?e.printStackTrace();

  59. ? ? ? ?}finally {

  60. ? ? ? ? ? ?//结束统计响应时间标记

  61. ? ? ? ? ? ?result.sampleEnd();

  62. ? ? ? ?}

  63. ? ? ? ?return result;

  64. ? ?}

  65. ? ?//测试结束方法

  66. ? ?public void tearDownTest(JavaSamplerContext context) {

  67. ? ? ? ?if (client != null) {

  68. ? ? ? ? ? ?client.close();

  69. ? ? ? ?}

  70. ? ? ? ?super.teardownTest(context);

  71. ? ?}

  72. }


特别说明:

  1. result.setSamplerLabel("7D"); //设置java Sampler的标题

  2. result.setResponseOK(); ? //设置响应成功

  3. result.setResponseData(); //设置响应内容

编写测试Run Main方法

  1. public class RunMain {

  2. ? ?public static void main(String[] args) {

  3. ? ? ? ?Arguments arguments = new Arguments();

  4. ? ? ? ?arguments.addArgument("ip","172.16.14.251");

  5. ? ? ? ?arguments.addArgument("port","9999");

  6. ? ? ? ?arguments.addArgument("X","1");

  7. ? ? ? ?arguments.addArgument("Y","3");

  8. ? ? ? ?arguments.addArgument("type","0");

  9. ? ? ? ?JavaSamplerContext context = new JavaSamplerContext(arguments);

  10. ? ? ? ?TestThriftByJmeter jmeter = new TestThriftByJmeter();

  11. ? ? ? ?jmeter.setupTest(context);

  12. ? ? ? ?jmeter.runTest(context);

  13. ? ? ? ?jmeter.tearDownTest(context);

  14. ? ?}

  15. }


测试结果通过

性能工具之Jmeter压测Thrift RPC服务

使用?mvn cleanpackage打包测试代码

性能工具之Jmeter压测Thrift RPC服务

使用?mvn dependency:copy-dependencies-DoutputDirectory=lib复制所依赖的jar包都会到项目下的lib目录下

性能工具之Jmeter压测Thrift RPC服务

复制测试代码?jar包到?jmeter\lib\ext目录下,复制依赖包到?jmeter\lib目录下

性能工具之Jmeter压测Thrift RPC服务

这里有两点需要注意:

  • 如果你的jar依赖了其他第三方jar,需要将其一起放到lib/ext下,否则会出现ClassNotFound错误

  • 如果在将jar放入lib/ext后,你还是无法找到你编写的类,且此时你是开着JMeter的,则需要重启一下JMeter

打开?Jmeter,在添加?Java请求时,注意要选择?Jmeter测试类,下面的列表中可以看到参数和默认值。

性能工具之Jmeter压测Thrift RPC服务

下面我们将进行性能压测,设置线程组,设置10个并发线程。

性能工具之Jmeter压测Thrift RPC服务

服务端日志:

性能工具之Jmeter压测Thrift RPC服务

性能工具之Jmeter压测Thrift RPC服务

上一篇:类型转换


下一篇:第九周