Seeds used car thinking and practice in Dubbo version upgrade, multi-room programs of

Foreword

With the continuous development of seeds business, gradually expand the scale of the system, currently on a private cloud seeds have been running hundreds of applications Dubbo, Dubbo thousands of instances. Seeds of various departments rapid development of business, there is no time to unified version, each department has its own usage. With the construction of the second room, a unified demand Dubbo version becoming increasingly urgent. A few months ago, the company has undergone a related accidents and Dubbo, became the company's community-based Dubbo version 2.7.3 upgrade incentives.

Next, I will start from this line accident, this time we talk about Dubbo version upgrades made history Dubbo and subsequent multi-room solutions Our planning.

A, Ephermal node is not promptly remove lead provider can not restore the registration of bug fixes

Accident background

Zookeeper cluster as a common registry dubbo in a production environment, each service line seeds inside. September 2019, the engine room of a switch failure, leading to the emergence of network clusters zookeeper fluctuations in a few minutes. After zookeeper cluster recovery, dubbo under normal circumstances provider should quickly re-register to the zookeeper, but there is a small part of the provider for a long time not to re-register the zookeeper, manually restart the application until after the recovery registered.

Investigation process

First of all, we have statistics release distribution service dubbo this phenomenon and found that there is such a problem in most dubbo version, the proportion of the service and the problem is relatively low, at github issues, we have not found of issues. Therefore, it is concluded that a not yet fixed and fluctuations in scene of sporadic network problems.

Then, we put the log application problems arise, zookeeper log and dubbo the code logic to confirm each other. In the application log, the application reconnection after a successful provider immediately zookeeper has been re-registration, no log after they print. The zookeeper log in after registering the node is removed and not re-create the registered node. Corresponds to dubbo code, only in FailbackRegistry.register(url)the doRegister(url)case of performing success or the thread is suspended, in order to coincide with the log situation.

Before you continue troubleshooting, let these universal concepts: dubbo default curator as a zookeeper client, curator and zookeeper is through the session to maintain the connection. When the curator reconnection zookeeper, if the session has not expired, continue to use the original session connection; if the session has expired, you create a new session reconnect. The ephemeral nodes session is the relationship between bound, after session expires, deletes ephemeral nodes in this session.

Continue to doRegister(url)the code of conduct further investigation, we found that CuratorZookeeperClient.createEphemeral(path)there are so some logical ways: in createEphemeral(path)captured NodeExistsExceptionwhen creating ephemeral nodes, the nodes already exist if this is considered successfully created ephemeral nodes. Early this logic seems to be no problem, and the performance of normal in the following two common scenarios:

  1. Session has not expired, the original node still exists when you create Ephemeral nodes do not need to re-create
  2. Session has expired, the original node has been deleted zookeeper when creating Ephemeral node, create a success

但是实际上还有一种极端场景,zookeeper的Session过期与删除Ephemeral节点不是原子性的,也就是说客户端在得到Session过期的消息时,Session对应的Ephemeral节点可能还未被zookeeper删除。此时dubbo去创建Ephemeral节点,发现原节点仍存在,故不重新创建。待Ephemeral节点被zookeeper删除后,便会出现dubbo认为重新注册成功,但实际未成功的情况,也就是我们在生产环境遇到的问题。

此时,问题的根源已被定位。定位问题之后,经我们与 Dubbo 社区交流,发现考拉的同学也遇到过同样的问题,更确定了这个原因。

问题的复现与修复

定位到问题之后,我们便开始尝试本地复现。由于zookeeper的Session过期但Ephemeral节点未被删除的场景直接模拟比较困难,我们通过修改zookeeper源码,在Session过期与删除Ephemeral节点的逻辑中增加了一段休眠时间,间接模拟出这种极端场景,并在本地复现了此问题。

在排查问题的过程中,我们发现kafka的旧版本在使用zookeeper时也遇到过类似的问题,并参考kafka关于此问题的修复方案,确定了dubbo的修复方案。在创建Ephemeral节点捕获到NodeExistsException时进行判断,若Ephemeral节点的SessionId与当前客户端的SessionId不同,则删除并重建Ephemeral节点。在内部修复并验证通过后,我们向社区提交了issues及pr。

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

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

二、瓜子的dubbo升级历程

上文中的问题修复方案已经确定,但我们显然不可能在每一个dubbo版本上都进行修复。在咨询了社区dubbo的推荐版本后,我们决定在dubbo2.7.3版本的基础上,开发内部版本修复来这个问题。并借这个机会,开始推动公司dubbo版本的统一升级工作。

为什么要统一dubbo版本

  1. 统一dubbo版本后,我们可以在此版本上内部紧急修复一些dubbo问题(如上文的dubbo注册故障恢复失效问题)。
  2. 瓜子目前正在进行第二机房的建设,部分dubbo服务也在逐渐往第二机房迁移。统一dubbo版本,也是为dubbo的多机房做铺垫。
  3. 有利于我们后续对dubbo服务的统一管控。
  4. dubbo社区目前的发展方向与我们公司现阶段对dubbo的一些诉求相吻合,如支持gRPC、云原生等。

为什么选择dubbo2.7.3

  1. 我们了解到,在我们之前携程已经与dubbo社区合作进行了深度合作,携程内部已全量升级为 2.7.3 的社区版本,并在协助社区修复了 2.7.3 版本的一些兼容性问题。感谢携程的同学帮我们踩坑~
  2. dubbo2.7.3版本在当时虽然是最新的版本,但已经发布了2个月的时间,从社区issues反馈来看,dubbo2.7.3相对dubbo2.7之前的几个版本,在兼容性方面要好很多。
  3. 我们也咨询了dubbo社区的同学,推荐升级版本为2.7.3。

内部版本定位

基于社区dubbo2.7.3版本开发的dubbo内部版本属于过渡性质的版本,目的是为了修复线上provider不能恢复注册的问题,以及一些社区dubbo2.7.3的兼容性问题。瓜子的dubbo最终还是要跟随社区的版本,而不是开发自已的内部功能。因此我们在dubbo内部版本中修复的所有问题均与社区保持了同步,以保证后续可以兼容升级到社区dubbo的更高版本。

兼容性验证与升级过程

我们在向dubbo社区的同学咨询了版本升级方面的相关经验后,于9月下旬开始了dubbo版本的升级工作。

  1. 初步兼容性验证
    首先,我们梳理了一些需要验证的兼容性case,针对公司内部使用较多的dubbo版本,与dubbo2.7.3一一进行了兼容性验证。经验证,除dubboX外,dubbo2.7.3与其他dubbo版本均兼容。dubboX由于对dubbo协议进行了更改,与dubbo2.7.3不兼容。
  2. 生产环境兼容性验证
    在初步验证兼容性通过后,我们与业务线合作,挑选了一些重要程度较低的项目,在生产环境对dubbo2.7.3与其他版本的兼容性进行了进一步验证。并在内部版本修复了一些兼容性问题。
  3. 推动公司dubbo版本升级
    在10月初,完成了dubbo兼容性验证后,我们开始在各个业务线推动dubbo的升级工作。截止到12月初,已经有30%的dubbo服务的完成了版本升级。按照排期,预计于2020年3月底前完成公司dubbo版本的统一升级。

兼容性问题汇总

在推动升级dubbo2.7.3版本的过程整体上比较顺利,当然也遇到了一些兼容性问题:

  • 创建zookeeper节点时提示没有权限
    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多机房方案

瓜子目前正在进行第二机房的建设工作,dubbo多机房是第二机房建设中比较重要的一个话题。在dubbo版本统一的前提下,我们就能够更顺利的开展dubbo多机房相关的调研与开发工作。

初步方案

我们咨询了dubbo社区的建议,并结合瓜子云平台的现状,初步确定了dubbo多机房的方案。

  1. 在每个机房内,部署一套独立的zookeeper集群。集群间信息不同步。这样就没有了zookeeper集群跨机房延迟与数据不同步的问题。
  2. dubbo服务注册时,仅注册到本机房的zookeeper集群;订阅时,同时订阅两个机房的zookeeper集群。
  3. 实现同机房优先调用的路由逻辑。以减少跨机房调用导致的不必要网络延迟。

同机房优先调用

dubbo同机房优先调用的实现比较简单,相关逻辑如下:

  1. 瓜子云平台默认将机房的标志信息注入容器的环境变量中。
  2. provider暴露服务时,读取环境变量中的机房标志信息,追加到待暴露服务的url中。
  3. consumer调用provider时,读取环境变量中的机房标志信息,根据路由策略优先调用具有相同标志信息的provider。

  针对以上逻辑,我们简单实现了dubbo通过环境变量进行路由的功能,并向社区提交了pr。
  dubbo通过环境变量路由pr: https://github.com/apache/dubbo/pull/5348

作者介绍:李锦涛,任职于瓜子二手车基础架构部门,负责瓜子微服务架构相关工作。目前主要负责公司内 Dubbo 版本升级与推广、 Skywalking 推广工作。

 

本文作者:李锦涛

原文链接

本文为阿里云内容,未经允许不得转载。

Guess you like

Origin www.cnblogs.com/zhaowei121/p/12161158.html