1.业界方案-瓜子二手车在 Dubbo 版本升级、多机房方案方面的思考和实践(1)

前言

系统规模扩大,私有云上数百个 Dubbo 应用,上千个 Dubbo 实例。版本没统一,发生与 Dubbo 相关事故,成为升级的诱因。

一、Ephermal节点未及时删除导致provider不能恢复注册的问题修复

事故背景

各业务线共用zookeeper集群作为dubbo注册中心。19年9月,一台交换机故障,导致zk集群几分钟网络波动。zk集群恢复后,正常dubbo的provider很快重新注册到zk上,但小部分没有,直到手动重启恢复

排查过程

1、统计这种现象dubbo服务版本分布,大多数都存在,github未找到相关问题issues。推断尚未修复的偶现问题。

2、应用、zk日志dubbo代码逻辑相互印证

应用日志:应用重连zk后provider立刻重新注册,之后没有日志打印。

zk日志:注册节点被删除后,并没有重新创建注册节点。

对应dubbo代码:只有在FailbackRegistry.register(url)的doRegister(url)执行成功或线程被挂起情况下,才与日志情况吻合。

ps:dubbo默认curator为zk客户端,curator与zk通过session连接。当curator重连zk时,session未过期用原;过期创建新的。ephemeral节点与session绑定,session过期,删除此session下ephemeral节点。

3、继续对doRegister(url)排查,发现CuratorZookeeperClient.createEphemeral(path)中:在createEphemeral(path)捕获了NodeExistsException,创建ephemeral节点时,若此节点已存在为创建成功。初看没问题,且在以下两种常见的场景下表现正常:

Session未过期,创建Ephemeral节点时原节点仍存在,不需要重新创建

Session已过期,创建Ephemeral节点时原节点已被zookeeper删除创建成功

极端场景,zookeeper的Session过期与删除Ephemeral节点不是原子性的,Session过期,Ephemeral节点未被zookeeper删除。创建发现存在,不重新创建。待Ephemeral节点被zookeeper删除后,dubbo认为重新注册成功,实际未成功。定位问题后,与 Dubbo 社区交流,考拉也遇到。

问题的复现与修复

在Session过期与删除Ephemeral节点加休眠时间,复现。

排查问题过程中,发现kafka的旧版本在用zk时也遇到过类似的问题,参考kafka修复方案,确定dubbo修复方案。在创建Ephemeral节点捕获到NodeExistsException时进行判断,若Ephemeral节点的SessionId当前客户端的SessionId不同,删除并重建Ephemeral节点。

kafka类似问题issues:https://issues.apache.org/jira/browse/KAFKA-1387

dubbo注册恢复问题issues:https://github.com/apache/dubbo/issues/5125

二、瓜子的dubbo升级历程

决定在dubbo2.7.3版本修复,兼容性好: 与其他dubbo版本均兼容,除dubboX外(对dubbo协议进行了更改)

1、为什么要统一dubbo版本?

在此版本上修复问题;为dubbo的多机房、统一管控做铺垫。

dubbo社区发展方向与公司对dubbo诉求吻合,如支持gRPC、云原生等

兼容性问题汇总(这部分没看)

创建zk节点时提示没有权限

dubbo配置文件中已经配置了zookeeper的用户名密码,但在创建zookeeper节点时却抛出KeeperErrorCode = NoAuth的异常,这种情况分别对应两个兼容性问题:

参考社区的pr,我们在内部版本进行了修复。

issues:https://github.com/apache/dubbo/issues/5076

dubbo在未配置配置中心时,默认使用注册中心作为配置中心。通过注册中心的配置信息初始化配置中心配置时,由于遗漏了用户名密码,导致此问题。

issues:https://github.com/apache/dubbo/issues/4991

dubbo在建立与zookeeper的连接时会根据zookeeper的address复用之前已建立的连接。当多个注册中心使用同一个address,但权限不同时,就会出现NoAuth的问题。

curator版本兼容性问题

dubbo2.7.3与低版本的curator不兼容,因此我们默认将curator版本升级至4.2.0

分布式调度框架elastic-job-lite强依赖低版本的curator,与dubbo2.7.3使用的curator版本不兼容,这给dubbo版本升级工作带来了一定阻塞。考虑到elastic-job-lite已经很久没有人进行维护,目前一些业务线计划将elastic-job-lite替换为其他的调度框架。

openFeign与dubbo兼容性问题

issues:https://github.com/apache/dubbo/issues/3990

dubbo的ServiceBean监听spring的ContextRefreshedEvent,进行服务暴露。openFeign提前触发了ContextRefreshedEvent,此时ServiceBean还未完成初始化,于是就导致了应用启动异常。

参考社区的pr,我们在内部版本修复了此问题。

RpcException兼容性问题

dubbo低版本consumer不能识别dubbo2.7版本provider抛出的org.apache.dubbo.rpc.RpcException。因此,在consumer全部升级到2.7之前,不建议将provider的com.alibaba.dubbo.rpc.RpcException改为org.apache.dubbo.rpc.RpcException

qos端口占用

dubbo2.7.3默认开启qos功能,导致一些混部在物理机的dubbo服务升级时出现qos端口占用问题。关闭qos功能后恢复。

自定义扩展兼容性问题

业务线对于dubbo的自定义扩展比较少,因此在自定义扩展的兼容性方面暂时还没有遇到比较难处理的问题,基本上都是变更package导致的问题,由业务线自行修复。

skywalking agent兼容性问题

我们项目中一般使用skywalking进行链路追踪,由于skywalking agent6.0的plugin不支持dubbo2.7,因此统一升级skywalking agent到6.1。

三、dubbo多机房方案

1、每个机房部署一套独立zk集群。集群间信息不同步。没有zk集群跨机房延迟数据不同步问题

2、dubbo仅注册本机房zk集群;同时订阅两机房zk集群。

3、同机房优先调用(实现简单):

云平台默认将机房标志信息注入容器的环境变量中。

provider暴露服务时,读取环境变量中的机房标志信息,追加到待暴露服务的url中

consumer调用provider时,读取环境变量中的机房标志信息,路由策略优先调用相同标志provider

实现dubbo通过环境变量进行路由的功能,向社区提交了pr:https://github.com/apache/dubbo/pull/5348

优点:一个故障,另一个ok; 服务同机房闭环,减少时间延迟。

缺点:双注册中心,机器成本增加

https://www.cnblogs.com/zhaowei121/p/12161158.html

你可能感兴趣的:(1.业界方案-瓜子二手车在 Dubbo 版本升级、多机房方案方面的思考和实践(1))