Dubbo之启动时检查
dubbo版本
- dubbo版本2.6.7
启动时检查
- 在启动时检查依赖的服务是否可用,缺省会在启动时检查依赖的服务是否可用(默认
check="true"
),不可用时会抛出异常,阻止 Spring 初始化完成 - 以下情况需要关闭
- 测试时,不关心部分服务。部分服务没有启动,但是不影响当前测试流程
- 循环依赖,必须有一方先启动
- 如果Spring是懒加载或者延迟引用服务,必须关闭check,否则服务临时不可用时,会抛出异常。拿到 null 引用,如果
check="false"
,总是会返回引用,当服务恢复时,能自动连上
配置示例
-
Spring方式配置
1. 关闭某个服务的启动时检查 <dubbo:reference interface="com.foo.BarService" check="false" /> 2. 关闭所有服务的启动时检查 <dubbo:consumer check="false" /> 3. 关闭注册中心启动时检查 <dubbo:registry check="false" />
-
dubbo.properties方式配置
# 单个服务配置 dubbo.reference.com.foo.BarService.check=false #强制改变所有 reference 的 check 值,就算配置中有声明,也会被覆盖 dubbo.reference.check=false #设置 check 的缺省值,如果配置中有显式的声明 dubbo.consumer.check=false #订阅失败时允许启动 dubbo.registry.check=false
-
通过启动参数
java -Ddubbo.reference.com.foo.BarService.check=false java -Ddubbo.reference.check=false java -Ddubbo.consumer.check=false java -Ddubbo.registry.check=false
源码分析
-
默认情况下(
check=true
),如果provider没有提供服务,consumer在启动时会报如下错误Failed to check the status of the service cn.jannal.dubbo.facade.DemoService. No provider available for the service group0/cn.jannal.dubbo.facade.DemoService:1.0.0 from the url zookeeper://dubbo-zookeeper:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-consumer&check=true&dubbo=2.0.2&group=group0&interface=cn.jannal.dubbo.facade.DemoService&methods=sayHello&pid=95169&qos.port=33333®ister.ip=172.16.117.33&revision=1.0.0&side=consumer×tamp=1640577310886&version=1.0.0 to the consumer 172.16.117.33 use dubbo version 2.6.7
-
报错的地方在
ReferenceConfig#createProxy
,可以看到,默认check设置为true,如果invoker不可用,在抛出异常。默认调用的是RegistryProtocol#refer
private T createProxy(Map<String, String> map) { ...省略... invoker = refprotocol.refer(interfaceClass, urls.get(0)); ...省略... Boolean c = check; if (c == null && consumer != null) { c = consumer.isCheck(); } if (c == null) { c = true; // default true } if (c && !invoker.isAvailable()) { // make it possible for consumer to retry later if provider is temporarily unavailable initialized = false; throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion()); } ...省略... }
-
RegistryProtocol#doRefer
里创建了RegistryDirectory,RegistryDirectory是一种动态目录服务,实现了NotifyListener,当注册中心服务配置发生变化后,RegistryDirectory 可收到与当前服务相关的变化。收到变更通知后,RegistryDirectory 可根据配置变更信息刷新 Invoker 列表MockClusterInvoker#isAvailable里调用的directory @Override public boolean isAvailable() { return directory.isAvailable(); } 所以上面的invoker.isAvailable() 本质就是调用RegistryDirectory#isAvailable() public boolean isAvailable() { if (isDestroyed()) { return false; } Map<String, Invoker<T>> localUrlInvokerMap = urlInvokerMap; if (localUrlInvokerMap != null && localUrlInvokerMap.size() > 0) { for (Invoker<T> invoker : new ArrayList<Invoker<T>>(localUrlInvokerMap.values())) { if (invoker.isAvailable()) { return true; } } } return false; }
服务分组
-
当一个接口有多种实现时,可以用 group 区分。
-
配置
服务 <dubbo:service group="feedback" interface="com.xxx.IndexService" /> <dubbo:service group="member" interface="com.xxx.IndexService" /> 引用 <dubbo:reference id="feedbackIndexService" group="feedback" interface="com.xxx.IndexService" /> <dubbo:reference id="memberIndexService" group="member" interface="com.xxx.IndexService" /> 任意组: <dubbo:reference id="barService" interface="com.foo.BarService" group="*" />
多版本
-
当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用
-
升级步骤
- 先升级一半提供者为新版本
- 再将所有消费者升级为新版本
- 将剩下的一半提供者升级为新版本
-
新老版本配置
<dubbo:service interface="com.foo.BarService" version="1.0.0" /> <dubbo:service interface="com.foo.BarService" version="2.0.0" /> <dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" /> <dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />
-
如果不需要区分版本,可以直接
<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端