上周遇到个关于升级dubbo 2.6 到2.7的兼容性问题,差点造成线上故障,这里记录下,也给大家提个醒。

问题回放

有一个接口的提供方(dubbo 2.6.6)这么配置接口的版本号

<dubbo:provider version="1.0.0"/>

消费方(也是dubbo 2.6.6)的reference这么配置

<dubbo:reference id="sampleService" version="1.0.0" check="false" interface="com.newboo.basic.api.SampleService"/>

然后升级消费方的dubbo版本,经过一通操作将消费者升级到dubbo 2.7.3,预发测试时发现调用报No provider,还好是在测试时发现,不然后果不堪设想

No provider available from registry 127.0.0.1:2181

根因分析

查看注册到注册中心的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&timestamp=1616848403414

可以看到它没有version字段,取而代之的是default.version字段

看一下dubbo中匹配version这个逻辑,位置在org.apache.dubbo.common.utils.UrlUtils类的isMatch方法,摘出重点部分

String consumerGroup = consumerUrl.getParameter(GROUP_KEY);
String consumerVersion = consumerUrl.getParameter(VERSION_KEY);
String consumerClassifier = consumerUrl.getParameter(CLASSIFIER_KEY, ANY_VALUE); String providerGroup = providerUrl.getParameter(GROUP_KEY);
String providerVersion = providerUrl.getParameter(VERSION_KEY);
String providerClassifier = providerUrl.getParameter(CLASSIFIER_KEY, ANY_VALUE);
return (ANY_VALUE.equals(consumerGroup) || StringUtils.isEquals(consumerGroup, providerGroup) || StringUtils.isContains(consumerGroup, providerGroup))
&& (ANY_VALUE.equals(consumerVersion) || StringUtils.isEquals(consumerVersion, providerVersion))
&& (consumerClassifier == null || ANY_VALUE.equals(consumerClassifier) || StringUtils.isEquals(consumerClassifier, providerClassifier));

逻辑很简单,就是provider和consumer URL上的version字段得匹配上,提供者没有version字段,只有default.version字段,很显然调用时报错。

但之前2.6.6是没有问题的,为什么?看了下2.6.6的实现,代码也是一样,但点进providerUrl.getParameter(VERSION_KEY);,发现它的实现不简单

public String getParameter(String key) {
String value = parameters.get(key);
if (value == null || value.length() == 0) {
value = parameters.get(Constants.DEFAULT_KEY_PREFIX + key);
}
return value;
}

先取key对应的值,取不到时,再加个前缀default.取一次,也就是说versiondefault.version两者只要有一个有值即可(version优先)。

反观2.7.3的实现就非常耿直

public String getParameter(String key) {
return parameters.get(key);
}

所以,这就直接导致了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方法,所以这个修复就是无效的了。


关于作者:专注后端的中间件开发,公众号"捉虫大师"作者,关注我,给你最纯粹的技术干货

升级 dubbo 小心 default.version的更多相关文章

  1. Tomcat启动服务报错:Unknown version string [3.1]. Default version will be used.

    用Intellij IDEA 部署Web项目,Tomcat启动后报错Unknown version string [3.1]. Default version will be used. 作者的问题出 ...

  2. 关于升级程序版本时version与build修改的问题

    CHENYILONG Blog 关于升级程序版本时version与build修改的问题 #问题#从V1.0升级到V1.0.1.version是一定要改的,那么build需要修改吗? #解答#一般习惯上 ...

  3. org.apache.tomcat.util.descriptor.web.WebXml.setVersion Unknown version string [4.0]. Default version will be used.报错

    org.apache.tomcat.util.descriptor.web.WebXml.setVersion Unknown version string [4.0]. Default versio ...

  4. Could not find JSON in http://updates.jenkins-ci.org/update-center.json?id=default&version=2.7.4

    14-Sep-2016 21:43:58.241 INFO [Download metadata thread] hudson.model.AsyncPeriodicWork$1.run Finish ...

  5. Tomcat启动服务报错:Unknown version string [4.0]. Default version will be used.

    Tomcat.jdk.web.xml 对应关系: 版本对应错误,更换便可.(版本往下兼容) web.xml——version2.2——JDK1.1——Tomcat3.3 web.xml——versio ...

  6. CentOS6.5升级autoconf版本 Autoconf version 2.64 or higher is required

    安装软件时提示说需要Autoconf 2.64或更高的版本 [root@BobServerStation twemproxy]# autoconf configure.ac:8: error: Aut ...

  7. Dubbo原理剖析 之 @DubboReference.version设置为*

    原文链接 Dubbo原理剖析 之 @DubboReference.version设置为* 1 背景 Dubbo在消费端提供了一个功能,即将消费者的版本号指定为*,那么不管服务端的接口版本是啥,都可以调 ...

  8. Dubbo -- 系统学习 笔记 -- 配置参考手册

    Dubbo -- 系统学习 笔记 -- 目录 配置参考手册 <dubbo:service/> <dubbo:reference/> <dubbo:protocol/> ...

  9. dubbo 官方参考手册~备案(防止哪天阿里一生气把dubbo给删除了)

          首页  ||  下载  ||  用户指南  ||  开发者指南  ||  管理员指南  ||  培训文档  ||  常见问题解答  ||  发布记录  ||  发展路线  ||  社区 E ...

随机推荐

  1. Java基础系列(36)- 数组三种初始化及内存分析

    内存分析 数组三种初始化 静态初始化 int[] a = {1,2,3}; Man[] mans = {new Man(1,1),new Man(2,2)} 动态初始化 int[] a = new i ...

  2. Linux系列(18) - 常用压缩命令(1)

    常用压缩格式 .zip .gz .bz2 .zip格式压缩/解压缩 命令格式 压缩 zip [压缩文件名] [源文件]:压缩文件 zip -r [压缩文件名] [源目录]:压缩目录 解压缩 unzip ...

  3. Linux系列(28) - 软件包简介

    软件包分类 源码包(脚本安装包) 优点 开源,如果有足够的能力,可以修改源代码: 可以自由选择所需的功能: 软件是编译安装,所以更加适合自己的系统,更加稳定.效率更高: 卸载方便: 缺点 安装过程步骤 ...

  4. 低代码+RPA+AI,能否让ERP焕发下一春?

    从2004年开始,国内ERP项目的实施便在各大企业热火朝天地展开,2014年,国内大中型企业已经基本完成了ERP系统的普及.ERP已经在大中型企业中成为不可或缺的关键信息系统.企业核心业务的流转与管控 ...

  5. javascript 定时器 timer setTimeout setInterval (js for循环如何等待几秒再循环)

    实现一个打点计时器,要求1.从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 12.返回的对象中需要包含一个 cance ...

  6. urllib2获取CGI请求的数据

    import urllib.request as urllib2 headers = { 'Authorization': 'Basic YWRtaW46YWRtaW4=', }#需要身份验证时,在请 ...

  7. kubeadm 如何将节点加入集群

    kubeadm join 使用 token 过期之后(24小时过期),如何加入集群 一.重启生成新token # 创建新token kubeadm token create # 查看是否存在有效的 t ...

  8. P5540-[BalkanOI2011]timeismoney|最小乘积生成树【最小生成树,凸壳】

    正题 题目链接:https://www.luogu.com.cn/problem/P5540 题目大意 给出\(n\)个点\(m\)条边边权是一个二元组\((a_i,b_i)\),求出一棵生成树最小化 ...

  9. Linux命令行:free

                  total        used        free      shared  buff/cache   availableMem:           251G   ...

  10. 一个Electron的设计缺陷及应对方案

    当你想实现阻止Electron窗口关闭,并弹出询问对话框,提示用户:"文章尚未保存,是否要关闭窗口"这类业务时,那么你99%会碰到这个BUG: https://github.com ...