Skip to main content

微服务如何实现主动下线?

作者:程序员马丁

在线博客:https://open8gu.com

note

大话面试,技术同学面试必备的八股文小册,以精彩回答应对深度问题,助力你在面试中拿个offer。

回答话术

1. 微服务主动下线

主动下线就是服务停机时先到注册中心注销,拒绝新的请求后,将旧的业务处理完成再停止进程。

在微服务架构中,单考虑优雅停机还不能实现平滑的发布,还需要要考虑主动下线。这个过程尤其需要考虑到服务发现和负载均衡的机制,一旦操作不够平滑,客户调用就会出现 503 或者 500 的情况。

2. 可能出现的问题

如果没有考虑优雅停机或主动下线场景,在发布新老版本或者重启服务时,可能会出现以下几种情况:

  • 服务进程已经收到的请求没有运行完成,JVM 就执行了进程中断,导致业务产生影响。
  • 未向注册中心发送注销本服务节点就停机了,这个时候网关调用到下线节点,就会出现 500。
  • 服务已经向注册中心发送了注销服务实例请求,但是等待时间不够,同样出现 500。

3. 主动下线流程

微服务架构下,常规主动下线流程如下:

  1. 注销服务实例:当一个服务实例准备关闭时,首先需要从服务发现的注册表中注销或标记为不可用。注册中心会通知到网关和各个服务列表监听者,需要等待监听者都得到了下线的消息并刷新了路由缓存;
  2. 完成未完成请求:服务实例继续处理已接收但未完成的请求。这确保了这些请求不会因为服务实例的关闭而中断,从而维持了服务的完整性和数据的一致性。也就是优雅停机的业务范畴;
  3. 停止路由新请求:因为第一步已经注销了自己在注册中心的实例,那么接下来的服务实例将不会再接受新的请求。在微服务架构中,这通常意味着负载均衡器将新的请求会路由到其他健康(或新启动)的服务实例。

问题详解

1. 基于 Nacos 注册中心的服务代码下线实现

Spring 也是基于 JVM 的停机钩子技术实现了自己的停机逻辑,然后调用 doClose 方法来关闭容器。

在 SpringBoot 2.3.0+ 版本里,新增优雅停机配置项。在框架层面即可实现优雅停机,并自动实现上述优雅停机步骤,低版本的解决办法也在后文给出了解决方案。

# 开启优雅停机,默认值:immediate 为立即关闭
server.shutdown=graceful

# 设置缓冲期,最大等待时间,默认:30秒
spring.lifecycle.timeout-per-shutdown-phase=60s

另外,还可以使用 actuator 的 shutdown 端点来实现停机操作,但是不建议在生产环境中使用,除非做好安全措施。

解锁付费内容,👉 戳