升级 dubbo,小心 default.version
上周遇到个关于升级 dubbo 2.6 到 2.7 的兼容性问题,差点造成线上故障,这里记录下,也给大家提个醒。
问题回放
有一个接口的提供方(dubbo 2.6.6)这么配置接口的版本号
消费方(也是 dubbo 2.6.6)的 reference 这么配置
然后升级消费方的dubbo版本
,经过一通操作将消费者升级到 dubbo 2.7.3,预发测试时发现调用报No provider
,还好是在测试时发现,不然后果不堪设想
根因分析
查看注册到注册中心的 URL 是这样
dubbo://10.0.0.6:20880/com.newboo.basic.api.SampleService?anyhost=true&application=ddog-provider-this-two&bind.ip=10.0.0.6&bind.port=20880&default.version=1.0.0&dubbo=2.0.2&generic=false&interface=com.newboo.basic.api.SampleService&methods=getByUid&owner=roshilikang&pid=82799&qos.accept.foreign.ip=true&qos.enable=true&side=provider×tamp=1616848403414
可以看到它没有version
字段,取而代之的是default.version
字段
看一下 dubbo 中匹配 version 这个逻辑,位置在org.apache.dubbo.common.utils.UrlUtils
类的isMatch
方法,摘出重点部分
逻辑很简单,就是 provider 和 consumer URL 上的version
字段得匹配上,提供者没有version
字段,只有default.version
字段,很显然调用时报错。
但之前 2.6.6 是没有问题的,为什么?看了下 2.6.6 的实现,代码也是一样,但点进providerUrl.getParameter(VERSION_KEY);
,发现它的实现不简单
先取 key 对应的值,取不到时,再加个前缀default.
取一次,也就是说version
和default.version
两者只要有一个有值即可(version 优先)。
反观 2.7.3 的实现就非常耿直
所以,这就直接导致了 2.7.3 调用 2.6.6 的 default.version 接口报错,类似的 group 也存在这个问题,甚至还有一些如 timeout 等参数都可能会失效。
这个问题还是比较明显,应该有人遇到,搜索了一下 github,果然让我找到了相关的 issue
来自:https://github.com/apache/dubbo/issues/5948
这个 issue 有一个相关联的修复,说是 2.7.7 已经修复了这个问题,于是我测试了一下 2.7.7,很遗憾,还是报错,看了下修复代码
和 2.6.6 的兼容不一样,这里修复是在 URL
类的 valueOf
方法中添加兼容逻辑,修复者想的是所有注册中心上的 URL 字符串最终得经过这个方法才能成为 URL 对象,才能为 dubbo 所用。
想法是没错,但通过调试发现并不是每个URL对象都来自valueOf方法
,2.7.7 中订阅时对提供者的 URL 进行处理的是URLStrParser
类的parseEncodedStr
方法,所以这个修复就是无效的了。
欢迎关注我的公众号 “捉虫大师”
版权声明: 本文为 InfoQ 作者【捉虫大师】的原创文章。
原文链接:【http://xie.infoq.cn/article/8d845c2dea01100f9320ddfd8】。文章转载请联系作者。
评论