基于jmeter-dubbo协议压测实践

背景

为了满足公司业务发展及性能要求,公司技术架构在很多业务接口调用设计中引用到了dubbo协议调用方式,对于以前HTTP feign调用的接口转为dubbo泛化调用后,接口性能如何?有何影响?需要进行压测评估。为解决公司RPC dubbo协议调用压测问题,需升级jmeter压测组件,扩展压测协议支持。

 

Dubbo泛化调用原理

在进行dubbo协议接口压测实施之前,我们有必要事先了解dubbo泛化调用的过程和原理。

 

所谓dubbo泛化调用即通常我们想调用别人的dubbo服务时,我们需要在项目中引入对应的jar包。而泛化调用的作用是,我们无需依赖相关jar包,也能调用到该服务。

dubbo泛化调用,主要涉及API方式和Spring方式,下面就是2种dubbo调用的简单代码示例:

packagecom.dewu.main.dubbo.provider.service.impl;

public interfacedubboHalloService {

StringsayHallo(String name);

}

API调用方式

ReferenceConfig<GenericService>referenceConfig=newReferenceConfig<>();

referenceConfig.setApplication(newApplicationConfig("test"));

referenceConfig.setRegistry(newRegistryConfig("8848"));

referenceConfig.setInterface("com.dewu.main.dubbo.provider.service.impl.dubboHalloService");

referenceConfig.setGeneric(true);

GenericServicegenericService=referenceConfig.get();

 

Objectresult=genericService.$invoke(

"hallo",

newString[]{"java.lang.String"},

newObject[]{"1234"});

 

System.out.println(result);

Spring调用方式

xml配置设置

<dubbo:reference id="dubboHalloService" interface="com.dewu.main.dubbo.provider.service.impl.dubboHalloService" generic="true" />

注入使用

@Service

publicclassPersonService{

 

@Resource(name="halloService")

privateGenericServicegenericService;

 

publicvoidsayHallo(){

Objectresult=genericService.$invoke(

"hallo",

newString[]{"java.lang.String"},

newObject[]{"1234"});

System.out.println(result);

}

}

 

在两种调用方式中,我们都需要使用被调用接口的字符串参数生成GenericService,通过GenericService的$invoke间接调用目标接口的接口。

public interface GenericService{

Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException;

}

 

泛化调用和直接调用在消费者者端,在使用上的区别是,我们调用服务时使用的接口为GenericService,方法为$invoker。在底层的区别是,消费者端发出的rpc报文发生了变化。

在使用上,不管哪种配置方式,我们都需要配置generic=true,设置generic=true后,RefereceConfig的interfaceClass会被强制设置为GenericService。

 

Jmeter压测组件实践使用

安装准备

https://github.com/thubbo/jmeter-plugins-for-apache-dubbo/releases/tag/2.7.8下载dubbo插件jmeter-plugins-dubbo-2.7.8-jar-with-dependencies.jar放置jmeter \lib\ext目录,或者下载使用jmeter-plugins-dubbo.jar,但此种方式需要引入如下相关依赖JAR包。

 

dubbo-2.5.3.jar

javassist-3.15.0-GA.jar

zookeeper-3.4.6.jar

zkclient-0.1.jar

jline-0.9.94.jar

netty-3.7.0-Final.jar

slf4j-api-1.7.5.jar

log4j-over-slf4j-1.7.5.jar

 

注意:此两种方式不能同时使用,否则会产生JAR包冲突

 

使用步骤

1.创建线程组->添加Dubbo Sample请求

 

2.配置注册中心地址,填写压测请求接口和方法以及请求体参数

3.点击运行,查看响应结果

 

组件详解

注册中心类型

 

 

  • Protocol=none为直连方式
  • Protocol=zookeeper使用zk注册中心
  • Protocol=使用nacas注册中心
  • Protocol=multicast为广播方式
  • Protocol=redis使用redis注册中心
  • Protocol=simple使用simple注册中心

 

请求参数描述

  1. 当使用zk,address填入zk地址(集群地址使用","分隔),使用dubbo直连,address填写直连地址和服务端口。
  2. timeout:服务方法调用超时时间(毫秒)。
  1. version:服务版本,与服务提供者的版本一致。
  2. retries:远程服务调用重试次数,不包括第一次调用,不需要重试请设为0。
  1. cluster:集群方式,可选方式类型:failover/failfast/failsafe/failback/forking。
  2. group: 服务分组,当一个接口有多个实现,可以用分组区分,必需和服务提供方一致。
  1. interface需要填写接口类型完整名称,含包名。
  2. 参数支持任何类型,包装类直接使用java.lang下的包装类,小类型使用:int、float、shot、double、long、byte、boolean、char,自定义类使用类完全名称。
  1. 参数值,基础包装类和基础小类型直接使用值,例如:int为1,boolean为true等,自定义类与List或者Map等使用json格式数据。

 

参数类型示例

 

 

Java类型

paramType

paramValue

int

int

1

int[]

int[]

[1, 2]

double

double

1.2

double[]

double[]

[1.2, 1.3]

short

short

1

short[]

short[]

[1, 2]

float

float

1.2

float[]

float[]

[1.2, 1.3]

long

long

1

long[]

long[]

[1, 2]

byte

byte

字节

byte[]

byte[]

字节

boolean

boolean

true

false

boolean[]

boolean[]

[true, false]

char

char

A,如果字符过长取值为:"STR".charAt(0)

char[]

char[]

[A, B]

java.lang.String

java.lang.String

String

string

"foo"

foo

java.lang.String[]

java.lang.String[]

String[]

string[]

["foo1", "foo2"]

java.lang.Integer

java.lang.Integer

Integer

integer

1

java.lang.Integer[]

java.lang.Integer[]

Integer[]

integer[]

[1, 2]

java.lang.Double

java.lang.Double

Double

1.2

java.lang.Double[]

java.lang.Double[]

Double[]

[1.2, 1.3]

java.lang.Short

java.lang.Short

Short

1

java.lang.Short[]

java.lang.Short[]

Short[]

[1, 2]

java.lang.Long

java.lang.Long

Long

1

java.lang.Long[]

java.lang.Long[]

Long[]

[1, 2]

java.lang.Float

java.lang.Float

Float

1.2

java.lang.Float[]

java.lang.Float[]

Float[]

[1.2, 1.3]

java.lang.Byte

java.lang.Byte

Byte

字节

java.lang.Byte[]

java.lang.Byte[]

Byte[]

字节

java.lang.Boolean

java.lang.Boolean

Boolean

true

false

java.lang.Boolean[]

java.lang.Boolean[]

Boolean[]

[true, false]

JavaBean

com.your.package.BeanName

{"att1":"foo","att2":"foo2"}

JavaBean[]

com.your.package.BeanName

[{"att1":"foo"}, {"att1":"foo2"}]

java.util.Map以及子类

java.util.Map以及子类

{"att1":"foo","att2":"foo2"}

java.util.Map<String,JavaBean>

java.util.Map

{"keyName":{"att1":"foo"}}

java.util.HashMap<Object,Object>

java.util.HashMap

{"keyName":{"att1":"foo"}}

java.util.Collection以及子类

java.util.Collection以及子类

["a","b"]

java.util.List<String>

java.util.List

["a", "b"]

java.util.List<JavaBean>

java.util.List

[{"att1":"foo1"}, {"att1":"foo2"}]

java.util.List<Map<Object, JavaBean>>

java.util.List

[{"keyName1":{"att1":"foo1"}}, {"keyName2":{"att1":"foo1"}}]

java.util.List<Long>

java.util.List

[1, 2, 3]

java.util.ArrayList<Object>

java.util.ArrayList

["foo" , 1, true]

 

踩坑指南

1.jar包冲突

2.缺少protostuff jar包依赖

3.参数格式问题导致调用报错

4.provide服务提供者注册出现问题导致连接拒绝

参考文档

https://github.com/thubbo/jmeter-plugins-for-apache-dubbo

posted @ 2021-06-17 21:32  禧子  阅读(531)  评论(0编辑  收藏  举报