微服务不停机更新

本文简单介绍关于 微服务 技术栈的对外无感知的优雅停机、更新和重启,仅通过一些微服务组件实现,不依赖容器技术。

1. 实现原理
实现对外透明的优雅更新的基本原理就是在原服务没有停机的时候启动一个新的进程,通过负载均衡让访问可以到达两个节点,然后将旧的服务“优雅”地下线,其本质是不接收新的请求,同时将正在处理中的请求完成,然后停机,之后的请求全部路由到新的服务上。
2. 服务架构
实现以上方案主要依靠 Spring Gateway 和 Nacos。
Spring Gateway 聚合内部的服务接口向外暴露,所有服务注册在 Nacos 上,在 Spring Gateway 上配置好 Nacos 使其动态路由到具体的服务而非写死 IP 和端口。
3. 具体细节
首先,优雅下线的配置是最简单的,在 Spring Boot 的配置文件中添加

server:
  shutdown: graceful

(Spring Boot 2.3+ 支持)
然后在停机时用 kill 命令就可以了,配置了优雅下线后会关闭各种连接、释放资源并主动从 Nacos 中注销。需要特别注意的是不能使用 kill -9 强制杀进程。

然后,因为需要能够在同一时间内运行两个服务,所以我们需要给它们指定不同的端口,一种较为简单的方式是在配置文件中将 server.port 配置为 0,这样启动时就会在本机没有占用的端口中随机使用一个,但缺点是无法指定端口的范围,因而我使用的是另一种方式,即在 shell 脚本中寻找一个端口然后在 jar 包的启动参数中指定。

shell 编写的大体思路是:

  1. 找到一个在指定范围内没被占用的端口,开启新的服务。
  2. 找到旧版本的进程然后 kill 关闭。

按道理说这样就行了,但是我在实际测试中发现在旧服务关闭的短暂时间内会有 Gateway 仍然路由到旧服务然后报错的情况,当前的解决方案是在关闭服务前先调用 Nacos 的 API 将旧实例从中注销,过一段时间后再杀掉进程,还需要一段时间考察。

最后修改:2022 年 10 月 18 日
如果觉得我的文章对你有用,请点个赞吧~