InfoQ 极客传媒 15 周年庆征文| 迁移 Eureka 到 Nacos 之双注册双订阅模式
小伙伴们好呀,今天来填一下这个坑🕳 —— 将注册中心从 Eureka 迁移到 Nacos 🐷
这里面涉及到这个 双注册双订阅模式 ,下面让我们一起看看叭~ 😄
首先,为啥要迁移呢?🐖
主要是它对比其他注册中心,已经落后太多了🐖
就拿 Nacos 来说吧,不仅有 配置中心,管理界面,还能手动上下线,而且支持服务列表变更的消息推送模式(实时性高)
Eureka 1.x 的架构有些地方可以改进,比如 在客户端的 pull 模式下,增加这个消息推送模式,增加实时性;还有 集群,Eureka 只支持 AP ,各个客户端都能进行写请求✍ , 没有主从节点之分,各个节点之间通过相互复制来同步数据,无法保证一致性。Nacos 则有 AP 和 CP 两种选择,更灵活。
2019 年的某个会上,Spring 团队提出如何解决 Netflix 进入维护模式后的 SpringCLoud 组件选择问题。
就是 Eureka 早已进入维护模式啦!而且 long long ago ,官方就放弃了这个 Eureka2.X 版本的开发(看了下分支,6,7 年前的代码了),而且官方还说了不能用在生产上,后果自负😱(额 咱也不知道它有啥新特点,反正 SpringCloud 一直用的 1.x 版本。现在更新到 1.10 了🙃)
简单了解了这个背景后,咱们再来看看 4ye 搭建的这个 demo 🐷
Eureka 注册中心
比如 老项目中,使用的注册中心是 Eureka 。架构如下
代码也很简单,有三个模块。分别是
注册中心 : 搭建时选择 Eureka Server 即可。
服务提供者(provider): 搭建时选择 Eureka Discovery Client 和 **Spring Web **即可。
服务消费者(consumer):搭建时选择 Eureka Discovery Client 和 **Spring Web **即可。
然后依次启动注册中心,provider,consumer 即可。
访问 http://localhost:8772/hello/Java4ye 可以看到下面的内容。
双注册双订阅模式
接着,我们克隆上面的 provider 和 consumer 模块。
在 pom 文件中直接加入 Nacos 和 Eureka 。
启动时会抛出下面的异常信息 。(引入 Actuator 时会出现另一个,同样排除掉即可)
可以看到是自动装配时,不知道用哪个导致的异常。但是我们两个都要😝
这里只要在 application.properties 中把这个自动装配移除掉即可。
当然,秉着严谨的态度,我们在这两个类中打入相应的断点,可以看到他们都被创建了。
同时,也成功注册到这两个注册中心去了😄
这个时候,再次访问旧的客户端 8772 端口的,可以发现如下效果。
但是要注意,此时项目的架构变成这样,consumer 中只有 Eureka 的客户端,所以调用到的都是 Eureka 中心中的服务。此时流量不会走到 Nacos 这边
接着便是看客户端 consumer 正不正常,比如跑个一天看看。
稳定后,下一步就是 下线这个 provider ,然后看看正不正常了。同样稳定后,便是准备启动这个 双订阅的客户端了。
小实验
但是我这里做了一个小实验 哈哈 想看看不下线的情况,我这个 新客户端 上线后是使用哪个注册中心的服务多点。
所以,接着,我们就启动这个新的 consumer,一个双订阅的客户端。🐷
同样修改下配置文件即可。
这个时候,我们访问新的客户端。8872 端口的: http://localhost:8872/hello/Java4ye
发现无论怎么刷新,接口的返回值都是下面这个,无法达到负载均衡的效果 。(⊙o⊙)?
简单翻看了下源码,可以发现系统创建了三个 discoveryClient ,最后一个是兜底用的。
而且 nacos 排在第一个,这意味着从 nacos 的注册中心中找到服务的话,就不会调用到 Eureka 中的了。
了解了这个原理后,将 nacos 中的服务进行下线。
然后去刷新新的客户端,8872 端口的,可以发现,又出现了负载均衡的效果了。
而且得益于 Nacos 的服务列表变更推送机制,我们客户端可以实时感知到 服务列表的 变化,这个时候直接去刷新新客户端的接口,可以发现它已经切换到 Eureka 中了,没有延迟感!
所以当我们在迁移的过程中,如果发现 Nacso 上新的 provider 有什么异常时,可以将其下线先🐷 轻轻一点真的太方便了
优雅下线
结束上面的小实验,回到正常流程中,我们要来下线这个 provider 了。
这里就得考虑这个 优雅下线 的问题了。
网上的方案很多,这里用 Springboot 的 actuator 来实现。
这个 graceful 配置是 Springboot2.3 之后才有的,会让内嵌服务器拒绝外部请求,然后处理完已经在内部的请求后,进入关闭状态。
通过这个暴露的 api,去修改 eureka 中 service 的状态。
这里直接访问 curl "localhost:8771/actuator" 来获取我们注册的这个 API (可以看到我们 - 符号被吃掉了 坑🕳)
接着,我们通过这串请求,改变 Eureka 中服务的状态: DOWN。
然后,在等待若干时间后,应该是客户端 consumer 重新去拉取服务列表信息后。(哈哈 我没数)😝
不过我配了 10s ,然后我们不断刷新请求,会发现这个负载均衡的效果已经消失了。只剩新的 provider 提供的服务了🐖
然后在服务稳定一段时间后,可以通过 Prometheus 来观察这个旧的 provider 的 qps 等,当它已经没有啥流量进入了,便可以直接关闭下线了。( kill -9)
上线双订阅客户端
接着,上线这个 新的 consumer ,这里也没啥特别的了。
同样等系统稳定后,下线这个旧的客户端 consumer 了。🐖
而且从上面小实验环节中,我们可以知道流量会先来到这个 Nacos 中,确认里面没有这个服务的话,才去这个 Eureka 中查找。所以到这里,这个 Eureka 中的流量就会少了大部分了。
再次上线
到了这里,我们还不能直接关闭这个 Eureka,还得再次上线新版本的只有 Nacos 注册中心的 provider 和 consumer 🐷
这次的新版要注意这个负载均衡,我们去掉了 Netflix 后,得手动引入 SpringCloud 的 loadbalancer 组件。其他也就删删配置了。
同样的,稳定后,才去下线双订阅客户端 consumer,再下线双注册服务端 Provider,最后才下线这个 Eureka。 🐷
这里通过 Nginx 等去控制流量,将他们打到新的只订阅 Nacos 的 consumer 上,最后等双订阅的 consumer 客户端没啥流量就给它下线了。
接着,在 Nacos 上 ,下线那个双注册的服务,然后再去下线它。
最后就直接关闭 Eureka 了。
这样就完成了这个注册中心的迁移了🐖
整体流程
这里其实就是上线新版本后,等其稳定,下线旧版本的一个规则。🐖
关于应用的发布,这里就不多赘述了🐖,网上大把的 蓝绿发布,灰度发布,还有 K8s 的 pod 容器,docker 等环境下的决策。
最后
https://github.com/Java4ye/springcloud-alibaba-demo-4ye
整个 demo 我也弄到 GitHub 上啦,新开的坑🕳 哈哈,后面也会逐步完善的😝
觉得不错的话,可以 Star 支持一波哦😝
总结
通过本案例,可以快速了解到这个迁移过程中:
这个代码基本都没改!这得益于这个 SpringCloud 的统一服务注册和发现的编程模型
使用双注册双订阅模型时,要排除掉自动装配的坑🕳,而且在这个模式下,流量基本都跑到 Nacos 这边。
对比下两个注册中心,更能感觉到 Nacos 这么多便利的功能:上下线和服务列表变化的推送机制。
了解到 Springboot 在优雅下线这一块做的变化,谨记不要轻易 kill -9!
版权声明: 本文为 InfoQ 作者【4ye】的原创文章。
原文链接:【http://xie.infoq.cn/article/2f96bd08a0acd4fc462ac07f4】。文章转载请联系作者。
评论