Spring Boot 1.X 优雅停机的一种实现方式

目前部署在k8s上的springboot应用通过RollingUpdate的方式更新应用时发现以下情况:

一个新pod起来并经过health check检查可以接收流量之后会删除一个老pod。但是,删除老pod时,虽然没有新的流量进入老pod,该老pod中的java进程还有一些业务没有处理完毕就直接被kill掉。

因此,我们需要做到当新pod起来之后,老pod不接收新流量,但是已经在处理的流量请求处理完之后才能删除老pod。

其实,k8s本身对于pod是有一个terminationGracePeriodSeconds的配置项(默认是30秒)。当采用RollingUpdate方式更新应用时,一个新pod起来并经过health check后(如果配置了health check),则会通知k8s终止一个pod。k8s终止pod的生命周期如下(共5步):

  1. Pod被设置为Terminating状态,并从k8s的service/endpoint列表中删除。此时,Pod停止获得新流量。在Pod中运行的容器不会受到影响。
  2. preStop Hook被执行(如果deployment yaml中配置该项,默认没有配置)。preStop Hook是一个发送到Pod中的容器特殊命令或Http请求。
  3. K8S向Pod中的容器发送SIGTERM信号。这个信号让容器知道它们很快就会被关闭。
    SIGTERM比较友好,进程能捕捉这个信号, 根据您的需要来关闭程序。在关闭程序之前,您可以结束打开的记录文件和完成正在做的任务。 在某些情况下, 假如进程正在进行作业而且不能中断,那么进程可以忽略这个 SIGTERM信号。相对于kill ${pid}命令。
    对于SIGKILL信号,进程是不能忽略的。 这是一个 '“我不管您在做什么,立刻停止”'的信号。 假如您发送SIGKILL信号给进程,
    FreeBSD就将进程停止在那里。相对于kill -9 ${pid}命令
    SpringBoot应用的java process捕获到该SIGTERM信号时就会开始正常关闭自己。
  4. K8S等待优雅的终止(等待时间terminationGracePeriod

猜你喜欢

转载自blog.csdn.net/luliuliu1234/article/details/103738633