springboot 优雅停机_一文聊透 Dubbo 优雅停机

本文深入探讨了Dubbo服务框架在优雅停机上的实现,从2.5.x版本的简单方案到2.7.x的最终优化。文章通过分析不同层面的停机策略,如操作系统、Java、框架和容器,强调了优雅停机的重要性。在Dubbo中,优雅停机涉及注册中心通知、服务消费者避免请求下线提供者及处理在途请求。文章详细阐述了2.5.x版本的注销逻辑,包括注册中心和协议注销,以及Spring环境下的挑战和解决方案。最后,作者提到了Dubbo 2.7.x版本的改进,以更好地应对各种环境下的优雅停机需求。
摘要由CSDN通过智能技术生成

1 前言

一年之前,我(老徐)曾经写过一篇《研究优雅停机时的一点思考》,主要介绍了 kill -9,kill -15 两个 Linux 指令的含义,并且针对性的聊到了 Spring Boot 应用如何正确的优雅停机,算是本文的前置文章,如果你对上述概念不甚了解,建议先去浏览一遍,再回头来看这篇文章。这篇文章将会以 Dubbo 为例,既聊架构设计,也聊源码,聊聊服务治理框架要真正实现优雅停机,需要注意哪些细节。

本文的写作思路是从 Dubbo 2.5.x 开始,围绕优雅停机这个优化点,一直追溯到最新的 2.7.x。先对 Dubbo 版本做一个简单的科普:2.7.x 和 2.6.x 是目前官方推荐使用的版本,其中 2.7.x 是捐献给 Apache 的版本,具备了很多新的特性,目前最新的 release 版本是 2.7.4,处于生产基本可用的状态;2.6.x 处于维护态,主要以 bugfix 为主,但经过了很多公司线上环境的验证,所以求稳的话,可以使用 2.6.x 分支最新的版本。至于 2.5.x,社区已经放弃了维护,并且 2.5.x 存在一定数量的 bug,本文介绍的 Dubbo 优雅停机特性便体现了这一点。

优雅停机一直是一个非常严谨的话题,但由于其仅仅存在于重启、下线这样的部署阶段,导致很多人忽视了它的重要性,但没有它,你永远不能得到一个完整的应用生命周期,永远会对系统的健壮性持怀疑态度。

同时,优雅停机又是一个庞大的话题

  • 操作系统层面,提供了 kill -9 (SIGKILL)和 kill -15(SIGTERM) 两种停机策略
  • 语言层面,Java 应用有 JVM shutdown hook 这样的概念
  • 框架层面,Spring Boot 提供了 actuator 的下线 endpoint,提供了 ContextClosedEvent 事件
  • 容器层面,Docker :当执行 docker stop 命令时,容器内的进程会收到 SIGTERM 信号,那么 Docker Daemon 会在 10s 后,发出 SIGKILL 信号;K8S 在管理容器生命周期阶段中提供了 prestop 钩子方法
  • 应用架构层面,不同架构存在不同的部署方案。单体式应用中,一般依靠 nginx 这样的负载均衡组件进行手动切流,逐步部署集群;微服务架构中,各个节点之间有复杂的调用关系,上述这种方案就显得不可靠了,需要有自动化的机制。

为避免该话题过度发散,本文的重点将会集中在框架和应用架构层面,探讨以 Dubbo 为代表的微服务架构在优雅停机上的最佳实践。Dubbo 的优雅下线主要依赖于注册中心组件,由其通知消费者摘除下线的节点,如下图所示:

44cc7b50a60146e890241d51e51a7e8c.png

上述的操作旨在让服务消费者避开已经下线的机器,但这样就算实现了优雅停机了吗?似乎还漏掉了一步,在应用停机时,可能还存在执行到了一半的任务,试想这样一个场景:一个 Dubbo 请求刚到达提供者,服务端正在处理请求,收到停机指令后,提供者直接停机,留给消费者的只会是一个没有处理完毕的超时请求。

5eb8024e6c3fae618405b9754917ced1.png

结合上述的案例,我们总结出 Dubbo 优雅停机需要满足两点基本诉求:

  1. 服务消费者不应该请求到已经下线的服务提供者
  2. 在途请求需要处理完毕,不能被停机指令中断

优雅停机的意义:应用的重启、停机等操作,不影响业务的连续性。

3 优雅停机初始方案 — 2.5.x

为了让读者对 Dubbo 的优雅停机有一个最基础的理解,我们首先研究下 Dubbo 2.5.x 的版本,这个版本实现优雅停机的方案相对简单,容易理解。

3.1 入口类:AbstractConfig

public abstract class AbstractConfig implements Serializable { static { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { public void run() { ProtocolConfig.destroyAll(); } }, "DubboShutdownHook")); }}

在 AbstractConfig 的静态块中,Dubbo 注册了一个 shutdown hook,用于执行 Dubbo 预设的一些停机逻辑,继续跟进 ProtocolConfig.destroyAll() 。

3.2 ProtocolConfig

public static void destroyAll() { if (!destroyed.compareAndSet(false, true)) { return; } AbstractRegistryFactory.destroyAll(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值