Dubbo 系列(二)
注意:本系列为个人学习系列
一、dubbo 配置
配置原则
- vm运行时参数:-Ddubbo.protocol.port=20880
- consumer.xml中配置:<dubbo:protocol name=“dubbo” port=“20881”>< /dubbo:protocol>
- dubbo.properties:dubbo.protocol.port=20882
启动检查
-
Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check=“true”。
-
可以通过 check=“false” 关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。
-
另外,如果你的 Spring 容器是懒加载的,或者通过 API 编程延迟引用服务,请关闭 check,否则服务临时不可用时,会抛出异常,拿到 null 引用,如果 check=“false”,总是会返回引用,当服务恢复时,能自动连上。
-
通过 spring 配置文件
-
某个服务的启动时检查 (没有提供者时报错):
<dubbo:reference interface="com.guigu.gmall.service.UserService" id="userService" check="false">< /dubbo:reference>
-
所有服务的启动时检查 (没有提供者时报错):
<dubbo:consumer check=“false” /> -
注册中心启动时检查 (注册订阅失败时报错):
<dubbo:registry check=“false” />
-
-
也可以通过 dubbo.properties配置,通过-D参数配置,参见官网
错误:
IllegalStateException: Failed to check the status of the service com.example.service.UserService. No provider available for the service com.example.service.UserService from the url
生产者提供的接口:
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.example.service.TbTemplateService" ref="tbTemplateService"/>
<!-- 和本地bean一样实现服务 -->
<bean id="tbTemplateService" class="com.example.service.impl.TbTemplateServiceImpl"/>
消费者需要的:
<!-- 生成远程服务代理,可以和本地bean一样使用demoService
不生产 "com.example.service.UserService"
-->
<dubbo:reference id="userService" interface="com.example.service.UserService"/>
解决办法:
<!-- 第一种 -->
<dubbo:consumer check="false"/>
<!-- 第二种 -->
<dubbo:reference id="userService" check="false" interface="com.example.service.UserService"/>
超时
-
在提供方代码中添加休眠方法:
try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); }
-
如果没有做任何配置,则会使用< dubbo:consumer>的timeout,默认为1s,即提供方如果1s没有响应,即抛异常
-
设置<dubbo:reference interface=“com.guigu.gmall.service.UserService” id=“userService” check=“false” timeout=“5000”>< /dubbo:reference>, 这样是成功的
-
如果需要统一设置所有reference的超时时间,可以在
< dubbo:consumer>< /dubbo:consumer>设置 -
注意:如果同时在多处设置了超时,那么他们之间的配置覆盖关系可参见官网图
-
优先 上到下
总结:
方法级优先,接口级次之,全局配置再次之。
如果级别一样,则消费方优先,提供方次之。
测试:
生产者需要五秒后响应:
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
消费者只等 1 秒:
<dubbo:reference id="userService" timeout="1000" interface="com.example.service.TbTemplateService"/>
错误:
TimeoutException: Waiting server-side response timeout. start time: 2021-03-16 19:56:09.471, end time: 2021-03-16 19:56:10.473, client elapsed: 0 ms,
重试次数
- 重试次数,不包含第1次调用
- 测试1:在服务提供者方法第一句加输出,通过运行,可发现在超时时间内会打印重试次数,说明尝试次数不包含第1次
- 测试2:在服务提供者方法第一句加输出,启动服务,然后改端口号和输出语句,再启动,同时启动3个服务提供方,可发现会在不同的提供方打印,说明消费方会在不同的服务提供方进行尝试调用
- 通常可以在幂等条件(查询,删除,修改)下设置尝试次数,非幂等条件(添加)不设置尝试次数,0代表不尝试。
多版本:
- 当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
- 可以按照以下的步骤进行版本迁移:
- 在低压力时间段,先升级一半提供者为新版本
- 再将所有消费者升级为新版本
- 然后将剩下的一半提供者升级为新版本
version 选择实际引用的提供方版本,也可以是*,表示随机引用一个版本
<dubbo:service version="1.0" interface="com.example.service.TbTemplateService" ref="tbTemplateService"/>
本地存根
-
在消费方定义本地存根,实现UserService接口
package com.guigu.gmall.service.impl; -
关键代码
public class UserServiceStub implements UserService { private final UserService userService; //传入的是UserService远程的代理对象 public UserServiceStub(UserService userService) { super(); this.userService = userService; } @Override public List<UserAddress> getUserAddressList(String s) { if(!StringUtils.isEmpty(s)) return userService.getUserAddressList(s); return null; } }
-
在consumer.xml中配置本地存根
<dubbo:reference stub="com.guigu.gmall.service.impl.UserServiceStub"></dubbo:reference>