优雅停机的时机与任务顺序编排

优雅停机的时机

1、执行 kill 前提前触发下线

理想状态下,所有服务可以暴露出来的一个下线接口,我们可以通过运维的自动化脚本提前执行下线,然后等待片刻,再执行 kill pid

遗憾的是,我们运维层面并没有做此规定,但有两个接口可以达到类似的效果

1、dubbo 的 qos 接口

2、spring boot actuator 的 shutdown 端点

spring boot actuator 我们很多应用都没接入,而且有局限性,我们暂不考虑

dubbo qos 接口现在大部分应用都支持,而且运维层面也已经支持,但默认情况下我们拿不到 qos 的 offline 事件,不过可以通过 qos offline功能增强 实现

2、jvm 钩子函数

如果我们没有提前对服务中的任务进行下线,也可以通过 jvm 钩子函数进行优雅关停,相关可参考 spring 优雅停机

任务的顺序编排

举个栗子

1、某个应用停机时先关闭了数据库连接,后关闭了 kafka 消费,导致停机时 kafka 消费的部分数据入库失败,造成数据丢失

因此,我们要梳理清楚服务中所有任务的依赖关系,然后手动编排停机顺序

因为不同业务的情况都不一样,下面只给出一个大概的编排顺序,实际情况请自行抉择

@Component

public class SpringContextClosedListener implements ApplicationListener<ContextClosedEvent> {

  

  @Override

  public void onApplicationEvent(ContextClosedEvent event) {

    // 1. 关闭自身对外提供的服务,比如 http 服务,dubbo 服务(这个地方注意,不是直接关停 dubbo, 只是下线自己不再作为提供者,但你仍旧可以消费别人,嫌麻烦这一步可以先不做)

    // 2. 优雅关停项目自身的任务,比如 kafka 消费,定时任务,死循环任务拉取,延时队列拉取等

    // 3. 优雅关停线程池

    // 4. 优雅关停 dubbo (之所以放这么靠后,是因为怕上面有些任务依赖 dubbo)

    // 5. 关闭 mysql 连接,codis 连接,mongodb 连接 等 (这部分放到 spring bean 的销毁事件也行,毕竟他们是最后的)

  }

  

}

备注:dubbo 高版本默认的优雅停机也是通过 ContextClosedEvent 实现,如需要自己编排顺序,请阅读 dubbo优雅停机最佳实践和原理, 关于多个 ContextClosedEvent 顺序问题,请阅读 spring 优雅停机

上一篇:dubbo源码分析第二十二篇一dubbo负载均衡-ConsistentHashLoadBalance及一致性hash算法


下一篇:SpringCloud基本认知