当dubbo多注册中心碰上标签路由

简介: 今天的主角是标签路由和dubbo的多注册中心。标签路由在之前的文章《以为是青铜,没想到是王者的dubbo标签路由》中已经详细介绍过,多注册中心是dubbo可以使用多个注册中心来提供或者消费服务,利用多注册中心的特性可以搭建多机房。然而很不幸,当多注册中心遇上标签路由,却产生了一个bug。

背景介绍


今天的主角是标签路由和dubbo的多注册中心。标签路由在之前的文章《以为是青铜,没想到是王者的dubbo标签路由》中已经详细介绍过,多注册中心是dubbo可以使用多个注册中心来提供或者消费服务,利用多注册中心的特性可以搭建多机房。然而很不幸,当多注册中心遇上标签路由,却产生了一个bug


bug复现


在复现bug前需要介绍一下dubbo的版本,dubbo社区目前主力维护的有 2.6.x 和 2.7.x 两大版本,其中


  • 2.6.x 主要以 bugfix 和少量 enhancements 为主,因此能完全保证稳定性
  • 2.7.x 作为社区的主要开发版本,得到持续更新并增加了大量新 feature 和优化


2.6.x 版本的包名为 com.alibaba.dubbo,2.7.x 的包名为 com.apache.dubbo,不仅包名不同,两个版本之间还存在着大量的不兼容,网上有一篇关于携程升级dubbo 2.7.x的踩坑文章(点击阅读原文可查看),总结一句话就是2.6.x升级到2.7.x没有想象中的那么简单。


本文要介绍的bug来源于2.6.x版本,下面开始复现。


  • 下载dubbo源码并切换到2.6.x分支
  • 使用源码中的例子dubbo/dubbo-demo/dubbo-demo-provider和dubbo/dubbo-demo/dubbo-demo-consumer
  • 修改consumer与provider的注册中心配置,都连上两个不同的zk注册中心(什么注册中心不重要,也可以是别的,如nacos)
  • 启动两个provider,第一个provider直接启动,第二个provider修改一下监听端口,并且打上tag(-Ddubbo.provider.tag=lkxiaolou)
  • 启动consumer消费,发现报错


 640.png


按照对dubbo的认知来说,如果两个provider,其中一个带了tag,另一个不带,不带tag时请求则会路由到不带tag的provider上去,为什么会报错呢?


bug分析


从异常堆栈能看出是抛出异常的是AvailableCluster,dubbo的cluster即集群容错机制,总结一下2.6.x中内置的集群容错机制


  • FailoverCluster: 失败自动切换,依次调用每个provider,有成功才返回
  • FailFastCluster: 快速失败,失败直接抛出异常
  • FailsafeCluster: 安全失败,失败不抛出异常,而是返回空结果
  • FailbackCluster: 失败不抛出异常,返回空结果,并在后台等一会再次尝试调用
  • ForkingCluster: 并行调用,可设置并发数,只要有一个成功即返回结果
  • AvailableCluster: 调用前检查provider是否可用,全部不可用抛出 “No provider available in []” 异常
  • BroadcastCluster: 串行调用所有provider,只要有一个异常就抛出异常,否则返回最后一次调用的结果
  • MergeableCluster: 根据配置并行调用多个接口,返回合并后的结果,合并策略可以配置


有一点需要明确的是集群容错是需要显示的配置才生效,否则只会使用默认策略failover。


代码和配置中并没有指定使用AvailableCluster,但是从异常堆栈中却看到错误由它抛出,比较奇怪。对于这种可稳定复现的bug,调试最方便也最快。


首先断点打在异常抛出的位置,看调用栈,判断调用从哪里过来


640.jpg


然后根据堆栈反推


640.jpg


这里invokers为空,肯定有问题,跟进去


640.jpg


在走完了tagRouter的逻辑后,invokers就空了,另一个主角“标签路由”登场了 注意到,这里的两个invokers,其实是对注册中心的调用,而且都带上了tag


640.jpg


再去看一下AvailableCluster在dubbo源码中有没有被使用,果然找到了,也是和注册中心有关,在多注册中心时使用了AvailableCluster


640.jpg


经过一番源码的研究,发现dubbo在消费多注册中心时,会去看哪个注册中心是否可用,只用可用的注册中心,把对注册中心可用性判断也包装成了一次调用,即invoker,理论上没啥问题,但是问题出在它竟然带上了tag,tag从何而来?经过几次断点调试,发现它来自这里


640.png


即注册中心的Directory的URL会把每个provider的URL上的参数都合并过来,注释上也写的很清楚,参数配置有一套覆盖优先级,override优先级最高,override即在注册中心上的覆盖配置,如权重就可以通过override来配置,consumer次之,如调用的超时时间以consumer为准,provider最低,为默认配置。所以只要有一个provider带上了tag就会被合并到注册中心的URL上。


总结一下bug产生的原因:


  • dubbo在消费多注册中心时使用AvailableCluster包装对注册中心可用性的判断
  • dubbo对注册中心的调用invoker,合并了来自所有provider的参数
  • 对注册中心可用性判断的调用也经过了tag路由,不带tag的调用过滤了所有带tag的注册中心
  • 找不到可用的注册中心,报错


bug解决


去github上提个issue,有回复说2.7.x版本已经修复了该问题,升级2.7.x谈何容易。修复这个bug有两条路可走:第一,注册中心的invoker不要合并来自所有provider的参数,这条实现起来比较困难,因为它的逻辑和dubbo调用的逻辑混在一起,无法区分;第二可以让注册中心的调用不经过路由。这也是2.7.x的修复逻辑,dubbo 2.6.x会强制初始化两个路由,而2.7.x是靠传入参数来控制路由策略,初始化注册中心的StaticDirectory时就不初始化路由规则。


640.jpg


2.7.x版本使用了ZoneAwareCluster来代替2.6.x多注册中心的AvailableCluster,正是前面提到的多机房建设,它可以将注册中心用zone来标记隔离,每次调用时,选择和注册中心同一个zone里面的provider来调用,起到“就近调用“的作用。



相关文章
|
Dubbo 应用服务中间件 开发工具
以zookeeper作为注册中心的分布式服务框架dubbo的部署安装
以zookeeper作为注册中心的分布式服务框架dubbo的部署安装
|
缓存 Dubbo Java
Java面试题顶级理解!Dubbo注册中心挂了,服务还可以继续通信吗?
什么情况?一位工作了 5 年的 Java 程序员,竟然回答不出这个问题?说“Dubbo注册中心挂了, 服务之间还可以继续通信吗”?今天,我话2分钟时间给大家来聊一聊。
269 0
|
2月前
|
Dubbo 应用服务中间件 Apache
Dubbo 应用切换 ZooKeeper 注册中心实例,流量无损迁移
如果 Dubbo 应用使用 ZooKeeper 作为注册中心,现在需要切换到新的 ZooKeeper 实例,如何做到流量无损?
34 4
|
2月前
|
监控 Dubbo Java
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
这篇文章详细介绍了如何将Spring Boot与Dubbo和Zookeeper整合,并通过Dubbo管理界面监控服务注册情况。
176 0
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
|
4月前
|
Dubbo 网络协议 Java
深入掌握Dubbo服务提供者发布与注册原理
该文章主要介绍了Dubbo服务提供者发布与注册的原理,包括服务发布的流程、多协议发布、构建Invoker、注册到注册中心等过程。
深入掌握Dubbo服务提供者发布与注册原理
|
7月前
|
Dubbo Java 应用服务中间件
深度剖析:Dubbo使用Nacos注册中心的坑
2020年笔者在做微服务部件升级时,Dubbo的注册中心从Zookeeper切换到Nacos碰到个问题,最近刷Github又有网友提到类似的问题,就在这篇文章里做个梳理和总结。
深度剖析:Dubbo使用Nacos注册中心的坑
|
7月前
|
Dubbo Cloud Native 应用服务中间件
【Dubbo3 终极特性】「云原生三中心架构」带你探索 Dubbo3 体系下的配置中心和元数据中心、注册中心的原理及开发实战(中)
【Dubbo3 终极特性】「云原生三中心架构」带你探索 Dubbo3 体系下的配置中心和元数据中心、注册中心的原理及开发实战(中)
244 1
|
7月前
|
负载均衡 Dubbo Java
Dubbo 挂载到 Spring Cloud 注册中心
【2月更文挑战第12天】Dubbo 挂载到 Spring Cloud 注册中心
95 7
|
7月前
|
XML Dubbo Java
【Dubbo3高级特性】「框架与服务」 Nacos作为注册中心-服务分组及服务分组聚合实现
【Dubbo3高级特性】「框架与服务」 Nacos作为注册中心-服务分组及服务分组聚合实现
285 0
|
7月前
|
存储 Dubbo 应用服务中间件
SpringCloud | Dubbo 微服务实战——注册中心详解
SpringCloud | Dubbo 微服务实战——注册中心详解