Dubbo版本bug与基础框架版本迭代规范建议

前言

该文记录下项目开发中遇到过的Dubbo版本bug,并初步定一个基础框架版本迭代规范。

版本使用历史

我们项目的Dubbo版本在最初的开发阶段使用的是,2.6.4和2.7.0,截止目前,使用的是2.7.0和2.7.1不等。

Dubbo2.7.0

bug症状

provider中抛出了自定义异常,而consumer中捕获不到对应异常。

bug分析

此bug在2.7.1或往后版本已被修复。分析可直接看如下引用https://github.com/apache/dubbo/issues/3386:

原因是服务端抛出的异常被java的反射捕获,包装成了InvocationTargetException 然后客户端代理处理异常,发现InvocationTargetException不在接口声明的异常中,就再包装成 UndeclaredThrowableException了

比对了2.6.4和2.6.5,几乎就是重写了ReferenceAnnotationBeanPostProcessor。 评估后发现写转换工程太大了,最终决定修改ReferenceBeanInvocationHandler的invoke代码

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try{
return method.invoke(bean, args);
}catch(InvocationTargetException ite){
throw ite.getTargetException();
}
}

临时发布一个patch到本地maven仓中使用,期望未来修复吧

bug修复方案

目前,dubbo2.7.1后的版本是按照类似上面bug分析中的代码进行修复的。 如果是依然需要使用2.7.0版本的话,可使用Dubbo的filter把返回结果的对应exception拉出来。

Dubbo2.7.1

bug症状

ZooKeeper的对应服务的provider出现了一些失效的或重复的注册节点,导致重启provider服务时(重启consumer也一定某些情况下会),负载机制负载到失效节点上。

bug分析

此bug为只在2.7.1版本存在的bug已被修复。 分析引用github|bug report :

近期,关于升级到2.7.1版本后注册中心(多数是zookeeper)出现重复URL地址数据无法删除的情况,我们持续收到来自社区的issue报告。以下issue是几个典型的异常现象:#3785 #3770 #3920 #4013

经过问题排查我们定位到了问题的原因:在2.7.1版本中URL地址在zookeeper中被注册为持久persistent节点(2.7.0及之前注册的是临时emperal节点),这样当server进程异常终止无法进入正常优雅下线流程时,如进程崩溃、强行kill -9等,导致zookeeper已失效持久节点无法清空,最终导致脏数据的出现。

解决及规避方法:

  1. 上下线过程避免强行终止进程,保证让Dubbo进入优雅停机流程
  2. 官方2.7.2版本将会修复此问题,预计在6月初发布
  3. 对于已经产生的脏数据,考虑手动或ZK脚本予以清理,但此时要注意严格控制删选条件
  4. 2.7.1版本增加配置:

之前我对此还是存在疑问,为什么无效的持久化节点就出问题呢,dubbo不是有负载机制和重试机制么?

由于是持久化节点,导致dubbo多个invoker和有问题的Channel不能及时清理(通过zk的listener机制),只能等心跳失效才会清除掉旧的Channel并生成新的。所以,这些有问题的Channel在等到心跳失效前是被认好的,在实例重启间隔(此情况是,重启开始时间+超时时间)不足的情况下,会产生一直失效的情况。bug修复方案 增加配置,并删除zk错误数据(需谨慎)。

Dubbo spring boot starter 2.7.0

bug症状

当时是在项目选型开发阶段发现的,同时启用eureka和dubbo出现了启动问题。

bug分析&修复方案

如下链接中的分析与修复,可说的不多: github|[Bugfix] Dubbo Spring Boot 2.7.0 Environment Beans conflict in Spring Boot or Spring Cloud 2

基础框架版本迭代规范

当初,发现2.7.0的bug的时候,我迫不及待的用上了2.7.1,并在测试运行了一周就建议了同组同时更换版本,并上线了。 结果给线上引入了2.7.1这个更蛋疼更严重的bug 0.0 ,, 可以想到的是:

  • 使用开源产品要报着开放且谨慎的态度。
  • 使用了最新版
  • 对要使用的版本的change log和commit了解得不够仔细
  • 各类问题调试不够全面、放到测试沉淀的时间不够长

所以,我个人初步提出一些基础框架(spring、dubbo等等)的版本迭代规范:

  1. 不使用最新版本。
  2. 确定究竟是一直采用一个版本,有问题就修改源码等等还是采用小步迭代的方案(因为一下子从2.7.0升到2.7.10要比一个个版本跟着升级风险要大得多,所以,我个人偏向要不一直不升级要不稳步升级)。
  3. 有更新版本需求时需在后台群里提出更新目的、必要性等等供组内成员确认。
  4. 确定更新方案(比如,单个服务先更新,是否有更新次序等等)。
  5. 了解新版的change log和变更,关注新版的github相关issue和社区相关讨论。
  6. 一般需要在测试环境运行起码3-4周。

Reference

  1. dubbo官方文档
  2. github

results matching ""

    No results matching ""