首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Dubbo 2.7.1 踩坑记

Dubbo 2.7.1 踩坑记

作者头像
andyxh
发布2019-09-10 19:33:37
1.7K0
发布2019-09-10 19:33:37
举报
文章被收录于专栏:程序通事程序通事

Dubbo 2.7.1 踩坑记

Dubbo 2.7 版本增加新特性,新系统开始使用 Dubbo 2.7.1 尝鲜新功能。使用过程中不慎踩到这个版本的 Bug。

系统架构

Spring Boot 2.14-Release + Dubbo 2.7.1

现象

Dubbo 服务者启动成功,正常提供服务,消费者调用偶现失败的情况。错误如下图:

15583219929142ef5dbd0806c47d988aa1ad24920b1b6.png
15583219929142ef5dbd0806c47d988aa1ad24920b1b6.png

可以看出,主要原因为 cause: message can not send, because channel is closed。 但是检查提供者,却发现服务进程正常。

登陆 Dubbo admin 查看提供者服务,发现这个服务存在两个节点。

1558321992969f7ec73433dfc4c35a79484edb908d748.png
1558321992969f7ec73433dfc4c35a79484edb908d748.png

192.168.164.77 为测试服务器的 ip,提供者位于这台机器,而另一个 10.20.80.67 却是本地电脑的 IP,但是此时本地并未运行这个服务。

再次查看服务报错的原因,可以看到提供者调用l本地提供 RPC 的服务。由于本地服务已停止,导致调用失败。

这个问题在之前版本从未碰到,刚开始隐约记得 Dubbo 服务提供者注册使用 ZooKeeper 临时节点,服务断开,会删除该节点。

问题原因

在 Dubbo 主页搜索相关 issue,看到同样的问题 Dubbo-2.7.1 providers 重复注册.

查看相关回复,可以看到问题主要由于 dynamic 默认值变成 false ,而 2.7.1 之前版本默认不赋值,初始值为 null。

15583219929464f88d2277240422a93e80bf95ff69ec1.png
15583219929464f88d2277240422a93e80bf95ff69ec1.png

后续 PR 中已修复该问题 Fix issue 3785,修复代码将 dynamic 默认设置成 true。但是截止 20190515 该版本暂未发布。

源码分析

知道问题原因,这里我们从源码分析一下,为什么 dynamic 设置成 false 会导致该问题。

注:下面分析的是 Dubbo 2.7.1 的源码

下面我们使用 Dubbo xml 配置相关。

在 xml 配置中,可以在以下两个地方设置 dynamic 属性。

15583219930733ceca2a340fd49ce96bd3c9574ae065b.png
15583219930733ceca2a340fd49ce96bd3c9574ae065b.png

服务启动时将会使用 DubboNamespaceHandler 解析,注入 Spring 容器。

15583219929464afc4fc277e84dcfbf4c75adb2b97df3.png
15583219929464afc4fc277e84dcfbf4c75adb2b97df3.png

其中会将 provider 标签解析成 ProviderConfig 对象,service 标签解析成 ServiceBean 对象。

155832199300620acb303fee84d2ab16131920cacc700.png
155832199300620acb303fee84d2ab16131920cacc700.png

查看继承关系,可以看到以上两个类都继承 AbstractServiceConfig , dynamic 位于这个父对象中。

15583219930294e661481d55741d6a31110f373002ef1.png
15583219930294e661481d55741d6a31110f373002ef1.png

可以看到该字段默认值为 false

接着查看 Dubbo 服务导出过程,位于 ServiceBean#export,略过其他代码,我们直接跳到关键 ServiceConfig#doExportUrlsFor1Protocol

15583219930461ed4b203ed234f9092fe71e784a4ea85.png
15583219930461ed4b203ed234f9092fe71e784a4ea85.png

可以看到这里调用了多次 appendParameters 方法。 这个方法将利用反射,获取对象的中所有字段信息,然后添加到 map 中。其中字段名字为键值,字段实际值为内容。此时 map 键值内容为:

1558321993050358b0a09c89549f194de00ec97c25787.png
1558321993050358b0a09c89549f194de00ec97c25787.png

可以看到 map 中还有一个 default.dynamic,大家翻看代码自己思考一下,为什么会出现这个?

接着我们跳到后面:

1558321993054a18c4fbfc9984685a8daa45c011a5413.png
1558321993054a18c4fbfc9984685a8daa45c011a5413.png

在这里会将上面得到 map 组装到 URL 对象中,然后再注册到注册中心。。

由于注册中心使用的是 ZooKeeper,所以这里将会使用 ZookeeperRegistry 实现类。

1558321993020fa3f1b4cd5cc4566acb835e8c2bd14f4.png
1558321993020fa3f1b4cd5cc4566acb835e8c2bd14f4.png

首先查看 url##getParameter 方法,这里 Constants.DYNAMIC_KEY 值为 dynamic。

15583219930714b971def40924ad2891aa5eb33d04f02.png
15583219930714b971def40924ad2891aa5eb33d04f02.png

该方法会先从 parameters 中根据键值取值。若不存在,会再根据 default 作为前缀拼接再次取值。若还不存在则使用传入的默认值。

查看此时的 parameters 对象。

155832199307775de17130ae44fe5bcf445ae93d57de9.png
155832199307775de17130ae44fe5bcf445ae93d57de9.png

url.getParameter(Constants.DYNAMIC_KEY, true) 返回为 false。

然后分析 zkClient#create 方法,

15583219930223ed0dc3cf43b4191a26877d11056e84d.png
15583219930223ed0dc3cf43b4191a26877d11056e84d.png

由于 ephemeral 为 false,所以这个服务注册到 ZooKeeper 的节点为持久节点。

临时节点,客户端断开,会话超时后,ZooKeeper 将会自动删除这个节点。zookeeper-faq

面试题:服务提供者能实现失效踢出是什么原理(高频题)

服务宕机的时候,该节点由于是持久节点会永远存在,而且当服务再次重启的时候会将重新注册一个新节点。这样就导致 ZooKeeper 中存在额外失效的节点,且该节点还无法自然消除(除非手动调用 ZooKeeper 删除节点方法)。

总结

由于 Dubbo 2.7.2 暂未发布,所以建议若想使用 Dubbo 2.7 新功能的同学,使用 2.7.0 版本。若现在正在使用 2.7.2 版本,也不要慌张。只要服务不是异常宕机或者使用 kill -9 强制杀死进程,以上的现象将不会碰到。正常服务关闭的时候,Dubbo 服务会主动去 ZooKeeper 注销该服务,并删除这个节点。

还未使用该版本的同学们,建议使用 2.7.0 或者等 2.7.2 发布以后,再使用。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-05-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Dubbo 2.7.1 踩坑记
    • 系统架构
      • 现象
        • 问题原因
          • 源码分析
            • 总结
            相关产品与服务
            微服务引擎 TSE
            微服务引擎(Tencent Cloud Service Engine)提供开箱即用的云上全场景微服务解决方案。支持开源增强的云原生注册配置中心(Zookeeper、Nacos 和 Apollo),北极星网格(腾讯自研并开源的 PolarisMesh)、云原生 API 网关(Kong)以及微服务应用托管的弹性微服务平台。微服务引擎完全兼容开源版本的使用方式,在功能、可用性和可运维性等多个方面进行增强。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档