查看原文
其他

平滑迁移 Dubbo 服务的思考

The following article is from Kirito的技术分享 Author kiritomoe

前言

近日,有报道称在 HashCorp 的商业软件试用协议上发现,旗下所有商业产品禁止在中国境内使用、部署、安装,这其中就包含了 Terraform, Consul, Vagrant 等众多知名软件,其中 Consul 是一个在微服务领域的开源软件,可以用于做注册发现、配置管理等场景。


该新闻在国内发酵后,有人在 Twitter上咨询了HashCorp 公司的创始人,得到的回复是影响的软件仅限于 Vault 这款加密软件,目前 HashCorp 公司的官方网站上已经更新了相关的条款,明确了受影响的产品仅限 Vault 这一款产品。

Consul 开源版是否收到影响?

上面的条款里只提到了商业软件,那么开源的 Consul 是否受到影响呢?在 Github 的 Consul 仓库上,可以得知项目的 license 是 Mozilla Public License 2.0 ,这款许可证在 Apache 官网上是 Category B , 属于 Weak Copy Left 许可,那么它有哪些特点呢?

  1. 任何可以使用,复制,修改,重新分发该代码,包括商业目的使用。

  2. 如果修改了 MPL 协议许可下的源码,再重新发布这部分源码的话,必须保留原来 MPL 许可证不得更换。

  3. 如果基于该项目衍生出更大的项目,那么这部分工作可以使用新许可证的方式进行分发,只要没有修改原来 MPL 许可下的代码。(这也是为什么 Apache 项目的分发的源码中可以包含 MPL 协议下二进制文件的原因)

可以看到,MPL 通常被认为是介于 Apache License 和 GPL/LGPL 之间的一个折中方案。相对于 Apache License,MPL 2.0 要求修改了源码必须保持相同协议;相对于 GPL/LGPL, MPL 2.0 可以商用,同时衍生的作品在一定条件下也可以更换许可证类型。

总体来看的话,开源版 Consul 无论是私用还是商用都是不受限制的。但这也可能是一个警钟,如果对 Consul 还是有所顾忌的话,如何替代掉它呢?

在微服务领域,Consul 主要被用来做充当注册中心和配置中心,例如 Dubbo 和 SpringCloud 都有对应的支持。本文便以这个事为一个引子,介绍如何平滑地迁移 Dubbo 服务,达到替换注册中心的效果。

平滑迁移服务的定义和意义

如果 Dubbo 应用已经部署到生产环境并处于正常运行状态中,此时想将应用的注册中心替换,那么在迁移过程中,保证业务的平稳运行不中断一定是第一要义。我们将保证应用运行不中断,并最终达成注册中心替换的过程称为平滑迁移。可以类比为给飞行中的飞机替换引擎,在项目升级、框架调整等很多时候,现状和终态之间往往都有一个过度方案。

  • 平滑迁移可以避免终态方案一次性上线后出现和原有方案的不兼容性,规避了整体回归的风险

  • 没有哪个互联网公司可以承担的起:“自 xx 至 xx,系统维护一小时,期间服务将无法提供,请广大用户谅解” 这种停机升级方案。

平滑迁移过程

说到注册中心迁移,可能很多人第一时间都能想到双注册双订阅这种方案

双注册和双订阅迁移方案是指在应用迁移时同时接入两个注册中心(原有注册中心和新注册中心)以保证已迁移的应用和未迁移的应用之间的相互调用。

以 Consul 迁移到 Nacos 为例:

在迁移态下,一共有两种应用类型:未迁移应用,迁移中应用。我们所说的双注册双订阅都是指的【迁移中应用】。明白下面几个点,平滑迁移的过程一下子就清晰了:

  • 【未迁移应用】不做任何改动

  • 为了让【未迁移应用】调用到【迁移中应用】,要求【迁移中应用】不仅要将数据写到 Nacos,还要写回旧的 Consul,这是双注册

  • 为了让【迁移中应用】调用到【未迁移应用】,要求【迁移中应用】不仅要订阅 Nacos 的数据,还要监听旧的 Consul,这是双订阅

  • 当所有应用变成【迁移中应用】时,旧的 Consul 就可以光荣下岗了,至此平滑迁移完成。

在这个过程中,还可以灵活的变换一些规则,例如在迁移中后期,大部分应用在 Nacos 中已经有服务了,可以切换双订阅为单订阅,以验证迁移情况。并且在真实场景下,还会并存配置中心、元数据中心的迁移,过程会更加复杂。

Dubbo 平滑迁移方案 -- 多注册中心

Dubbo 多注册中心配置文档地址:http://dubbo.apache.org/zh-cn/docs/user/demos/multi-registry.html

本文的完整代码示例将会在文末提供,其中 Consul 注册中心搭建在本地,而 Nacos 注册中心使用的是阿里云的云产品:微服务引擎 MSE,其可以提供托管的 Nacos/Zookeeper/Eureka 等集群。

Dubbo 支持多注册中心的配置,这就为我们平滑迁移提供了很多的便利性。在使用 dubbo-spring-boot-starter 时,只需要增加如下的配置,即可配置多注册中心:

dubbo.registries.first.protocol=consul
dubbo.registries.first.address=localhost:8500

dubbo.registries.second.protocol=nacos
dubbo.registries.second.address=mse-kirito-p.nacos-ans.mse.aliyuncs.com:8848

在 Consul 控制台可以看到服务已经注册成功:

在 MSE 控制台可以看到 Nacos 服务也已经注册成功

并且,服务调用一切正常。你可能会想:前面讲了一堆,你告诉我改了两行配置就是平滑迁移了?我还是得好好纠正下这种想法,改代码从来都是最轻松的事,难的是在迁移中,时刻观察业务状况,确保服务不因为迁移有损。除此之外,还需要注意的是,Dubbo 自带的多注册中心方案因为框架实现的问题,存在一定的缺陷。

Dubbo 多注册中心的缺陷

在 Dubbo 的实现中,多个注册中心的地址是隔离的,地址不会融合。也就是说,当消费者如下配置后:

dubbo.registries.first.protocol=consul
dubbo.registries.first.address=localhost:8500

dubbo.registries.second.protocol=nacos
dubbo.registries.second.address=mse-kirito-p.nacos-ans.mse.aliyuncs.com:8848

会永远优先从 Consul 中读取服务地址,除非 Consul 中没有服务,才会尝试从 Nacos 中读取,顺序取决于配置文件中注册中心声明的先后。这可能不符合大多数人对多注册中心的直观认知,但没办法,Dubbo 就是这么设计的,我也尝试猜想了几个这么设计的可能性:

  • 多个注册中心没有感知到对方存在的必要,所以只能串行读取多个注册中心

  • Dubbo 本身模型不支持注册中心聚合,除非专门搞一个 AggregationRegistry 代理多个注册中心实现

  • 多个注册地址的 equals 方案难以确定,官方没有给出契约规范,即 ip 和 port 相同就可以认为同一个地址吗?

  • Dubbo 的多注册中心的设计并不只是为了适配平滑迁移方案,其他场景可能恰恰希望使用这种串行读取的策略

为了让读者有一个直观的感受,我用文末的 demo 进行了测试,让服务提供者 A1(端口号 12346) 只注册到 Nacos,服务提供者 A2(端口号为 12345) 只注册到 Consul,消费者 B 双订阅 Nacos 和 Consul。如下图所示,在测试初期,可以发现,稳定调用到 A1;期间,我手动 kill 了 A1,图中也清晰地打印出了一条地址下线通知,之后稳定调用到 A2。

这样的缺陷,会导致我们在平滑迁移过程中无法对未迁移应用和迁移中应用进行充分的测试。

Dubbo 平滑迁移方案 -- 注册中心聚合

注册中心聚合这个词其实是我自己想的,因为 Dubbo 官方文档并没有直接给出这种方案,而是由阿里云的微服务商业化 EDAS 团队提供的开源实现(ps,没错,就是我所在的团队啦)。其基本思路就是前文提到的,聚合多个注册中心的地址。使用方式也同样简单

引入依赖:

<dependency>
<groupId>com.alibaba.edas</groupId>
<artifactId>edas-dubbo-migration-bom</artifactId>
<version>2.6.5.1</version>
<type>pom</type>
</dependency>

增加配置:

application.properties 中添加注册中心的地址。

dubbo.registry.address = edas-migration://30.5.124.15:9999?service-registry=consul://localhost:8500,nacos://mse-kirito-p.nacos-ans.mse.aliyuncs.com:8848&reference-registry=consul://localhost:8500,nacos://mse-kirito-p.nacos-ans.mse.aliyuncs.com:8848

说明 如果是非 Spring Boot 应用,在 dubbo.properties 或者对应的 Spring 配置文件中配置。

  • edas-migration://30.5.124.15:9999

    多注册中心的头部信息。可以不做更改,ip 和 port 可以任意填写,主要是为了兼容 Dubbo 对 ip 和 port 的校验。启动时,如果日志级别是 WARN 及以下,可能会抛一个 WARN 的日志,可以忽略。

  • service-registry

    服务注册的注册中心地址。写入多个注册中心地址。每个注册中心都是标准的 Dubbo 注册中心格式;多个用,分隔。

  • reference-registry

    服务订阅的注册中心地址。每个注册中心都是标准的 Dubbo 注册中心格式;多个用,分隔。

验证该方案:

已经变成了随机调用,解决了多注册中心的缺陷。

迁移完成后,建议删除原注册中心的配置和迁移过程专用的依赖edas-dubbo-migration-bom,在业务量较小的时间分批重启应用。edas-dubbo-migration-bom 是一个迁移专用的依赖,虽然长期使用对您业务的稳定性没有影响,但其并不会跟随 Dubbo 的版本进行升级,为避免今后框架升级过程中出现兼容问题,推荐您在迁移完毕后清理掉,然后在业务量较小的时间分批重启应用。

说明:edas-dubbo-migration-bom 目前的 release 版本只支持 Dubbo 2.6,我在文末的代码中提供了 2.7 的支持,预计很快两个版本都会贡献给 Dubbo 开源社区。

彩蛋:阿里云微服务引擎 MSE 重磅升级,上线微服务治理中心

附录

本文测试代码地址:https://github.com/lexburner/dubbo-migration

-END-

更多精彩文章

1.面试官:小伙子,听说你看过ThreadLocal源码?万字图文深度解析ThreadLocal

2.服务端高并发分布式架构演进之路

3.探究关于 Class 文件的几个问题

4.15分钟理解KD树

5.Redis用过吗?用过。那讲一讲跳跃表Skip list吧

6.Hystrix原理与实战


如果你喜欢本文

请长按二维码,关注 Bella的技术轮子

转发至 朋友圈,是对我最大的支持

喜欢就点个在看

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存