一,dubbo协议的接口测试
1,dubbo简介
2,dubbo系统框架
- 组成:远程服务运行容器-Container,远程服务提供方-Provider、注册中心-Register、远程服务调用者-Consumer、监控中心-Monitor
3,dubbo支持协议
- dubbo3 triple
- dubbo2 协议
- rest 协议
- http 协议
- hessian 协议
- redis 协议
- thrift 协议
- gRPC 协议
- memcached 协议
- rmi 协议
- webservice 协议
4,dubbo+zk的注册中心流程
5,dubbo配置结构 - xml
5.1 provider:
* 声明dubbo服务提供者的名称:保证唯一性: <dubbo:application name="xx-provider" />
* 服务注册地址: <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
* 设置dubbo使用的协议名称和端口: <dubbo:protcol name="dubbo" prot="20880" />
* 暴露服务接口,引用实现类 : <dubbo:service interface="com.xx.service" ref="xxImpl"/>
* 加载业务接口的实现类到spring容器中 :<bean id="xxImpl" class="com.xx.serviceImpl" />
5.2 consumer:
<dubbo:application name="xx-consumer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:reference id="xx" check="false" interface="com.xx.service"/>
5.3 xml配置示例:
5.4 xml配置常用属性:
5.5 在不修改代码或xml配置的情况下,自定义provider和consumer的group,timeout等参数
(1)调用接口修改(-Ddubbo.reference.id.ppp=xxx)
* id为接口全名
* ppp为属性
* xxx为要修改的属性值
- 示例:dsp服务调用recall服务的lp分组:
-Ddubbo.reference.com.heytap.ad.show.recall.api.IRecallServiceV2.group=lp.7.irg
-Ddubbo.reference.com.heytap.ad.show.recall.api.IRecallServiceV2.timeout=5000
(2)服务本身修改(-Ddubbo.service.id.ServiceBeanversion:group:ppp=xxx)
* id、ppp、xxx同上
* version为实际版本号
* group为实际分组值
- 示例:recall服务配置lp分组供dsp调用
-Ddubbo.service.com.heytap.ad.show.recall.api.IRecallServiceV2.ServiceBean:com.heytap.ad.show.recall.api.IRecallServiceV2:2.0.0:7.irg.group=lp.7.irg
6, linux命令下的环境准备和安装
-
下载统一服务 zookeeper redis并启动
- zookeeper:cp conf/zoo_sample.cfg conf/zoo.cfg
bin/zkServer.sh start - redis:redis-server
- zookeeper:cp conf/zoo_sample.cfg conf/zoo.cfg
-
dubbo 管理控制台安装
- 启动命令:
git clone https://github.com/apache/dubbo-admin.git
cd dubbo-admin
git tag
git checkout 0.3.0
mvn clean package -DskipTests
#vim dubbo-admin-server/src/main/resources/application.properties
mvn --projects dubbo-admin-server spring-boot:run -Dserver.port=8080
#http://127.0.0.1:8080
-
安装完成后查看服务是否启动成功
-
dubbo demo环境
git clone https://github.com/apache/dubbo.git
cd dubbo
git tag
git checkout dubbo-2.7.4.1
cd dubbo-demo
7,dubbo常用测试方法
7.1, telnet 调用 - 手动调用
(1)telnet连接dubbo服务
- dubbo开启的telnet服务:telnet localhost 20880
nc localhost 20880 - qos服务开启的telnet服务:telnet localhost 22222
nc localhost 22222
(2)查询dubbo服务接口:
* ls:
ls: 显示服务列表
ls -l: 显示服务详细信息列表
ls XxxService: 显示服务的方法列表
ls -l XxxService: 显示服务的方法详细信息列表
* cd status pwd
* help
(3) invoke 调用(仅适用于json协议)
调用服务的方法
invoke XxxService.xxxMethod(1234, “abcd”, {“prop” : “value”}):
调用全路径服务的方法
invoke com.xxx.XxxService.XxxService.xxxMethod(1234, “abcd”, {“prop” : “value”})
调用服务的方法(自动查找包含此方法的服务)
invoke xxxMethod(1234, “abcd”, {“prop” : “value”}):
当有参数重载,或者类型转换失败的时候,可以通过增加 class 属性指定需要转换类
invoke xxxMethod({“name”:“zhangsan”,“age”:12,“class”:“org.xxx.Person”})
invoke com.xxx.xxxApiService({“3”:0.123, “class”:“java.util.HashMap”})
7.2, rpc 调用 - 通过代码实现调用接口
(1) 导入依赖
<!-- 添加spring依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!-- 添加dubbo依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.8</version>
</dependency>
<!-- 添加接口工程依赖-->
<dependency>
<groupId>com.ads.test</groupId>
<artifactId>demo-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
(2) 配置consumer
(3) dubbo2 接口:以 consumer 的角色去调用
public class DubboTest {
static DemoService demoService;
@BeforeAll
static void beforeAll() {
//上下文的初始化
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml");
context.start();
demoService = context.getBean("demoService", DemoService.class);
}
@Test
void sayHello() {
String res;
res = demoService.sayHello("seveniruby");
assertThat(res, startsWith("Hello seveniruby"));
res = demoService.sayHello("ceshiren.com");
assertThat(res, startsWith("Hello ceshiren.com"));
}
}
(4) dubbo3 接口:
-
dubbo3 的主推协议 triple
-
dubbo3 的使用
- 定义 pb 数据格式
- 生成 dubbo3 stub
- 引入 provider 并编写实现
- 部署启动 provider 并注册到 registry
- 通过 consumer 调用
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml");
context.start();
DemoService demoService = context.getBean("demoService", DemoService.class);
HelloRequest request = HelloRequest.newBuilder().setName("Hello").build();
HelloReply reply = demoService.sayHello(request);
System.out.println("result: " + reply.getMessage());
System.in.read();
7.3, 泛化调用
(1)泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过 GenericService 调用所有服务实现。 Dubbo Admin 就是使用此方式
(2)代码示例(仅了解)
// 引用远程服务 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
// 弱类型接口名
reference.setInterface("com.xxx.XxxService");
reference.setVersion("1.0.0");
// 声明为泛化接口
reference.setGeneric(true);
// 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用
GenericService genericService = reference.get();
// 基本类型以及Date,List,Map等不需要转换,直接调用
Object result = genericService.$invoke("sayHello", new String[] {"java.lang.String"}, new Object[] {"world"});
// 用Map表示POJO参数,如果返回值为POJO也将自动转成Map
Map<String, Object> person = new HashMap<String, Object>();
person.put("name", "xxx");
person.put("password", "yyy");
// 如果返回POJO将自动转成Map
Object result = genericService.$invoke("findPerson", new String[]
{"com.xxx.Person"}, new Object[]{person});
(3)json 泛化调用 2.7.12 版本之后支持
// 引用远程服务
ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
// 弱类型接口名
reference.setInterface("com.xxx.api.service.TestService");
reference.setGroup("dev");
reference.setVersion("1.0");
reference.setRetries(0);
// RpcContext中设置generic=gson
RpcContext.getContext().setAttachment("generic","gson");
// 声明为泛化接口
reference.setGeneric(true);
reference.setCheck(false);
GenericService genericService = ReferenceConfigCache.getCache().get(reference);
// 传递参数对象的json字符串进行一次调用
Object res = genericService.$invoke("setUser", new String[]{"com.xxx.api.service.User"}, new Object[]{"{'name':'Tom','age':24}"});
System.out.println("result[setUser]:"+res); // 响应结果:result[setUser]:{name=Tom, class=com.xxx.api.service.User, age=24}
(4) pb 协议的泛化调用
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
// 弱类型接口名
reference.setInterface(GenericService.class.getName());
reference.setInterface("com.xxx.XxxService");
// 声明为Protobuf-json
reference.setGeneric(Constants.GENERIC_SERIALIZATION_PROTOBUF);
GenericService genericService = reference.get();
Map<String, Object> person = new HashMap<String, Object>();
person.put("fixed64", "0");
person.put("int64", "0");
// 参考google官方的protobuf 3 的语法,服务的每个方法中只传输一个POJO对象
// protobuf的泛化调用只允许传递一个类型为String的json对象来代表请求参数
String requestString = new Gson().toJson(person);
// 返回对象是GoolgeProtobuf响应对象的json字符串。
Object result = genericService.$invoke("sayHello", new String[] {
"com.xxx.XxxService.GooglePbBasic$CDubboGooglePBRequestType"},
new Object[] {requestString});