Logo

Kubernetes + Spring Boot + Dubbo 优雅停机最佳实践

作者

在微服务架构中,Kubernetes(简称为 k8s)已经成为了不可或缺的基础设施管理工具。而Spring Boot和Dubbo作为常见的Java开发框架和RPC框架,在微服务中也广泛应用。在这篇博客中,我们将探讨如何在Kubernetes环境下,实现Spring Boot + Dubbo应用的优雅停机,确保服务不会出现中断或数据丢失的情况。

什么是优雅停机?

优雅停机是指在系统关闭前,保证已经接收到的请求可以被处理完毕,而不是立即断开连接导致请求失败。在微服务架构中,这一点尤为重要,因为可能有多个服务依赖于正在关闭的服务。优雅停机可以保证整个系统在维护或升级时不会因为单个服务的关闭而导致整体不可用。

实现优雅停机的步骤

1. 通过 Kubernetes 控制器配置 liveness 和 readiness 探针

在Kubernetes中,liveness探针用于检测容器是否还在运行,readiness探针用于检测容器是否已经准备好接收流量。通过合理配置这两个探针,可以确保在新的服务 pod 真正完成启动前,老的服务 pod 不会被 kill 掉。

apiVersion: v1
kind: Pod
metadata:
  name: spring-dubbo-pod
spec:
  containers:
  - name: spring-dubbo-container
    image: your-image
    livenessProbe:
      httpGet:
        path: /actuator/health
        port: 8080
      initialDelaySeconds: 30
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /actuator/health
        port: 8080
      initialDelaySeconds: 30
      periodSeconds: 10

2. 配置 Kubernetes preStop

Kubernetes 杀死 pod 时会发生以下 5 个步骤:

  1. Pod 切换到终止状态并停止接收任何新流量。 容器仍在 Pod 内运行。
  2. preStop 钩子,即执行特殊命令或 HTTP 请求,并发送到 pod 内的容器。
  3. SIGTERM 信号被发送到 pod,容器意识到它将很快关闭。
  4. Kubernetes 等待宽限期 (terminationGracePeriodSeconds)。 此等待与 preStop 挂钩和 SIGTERM 信号执行并行(默认 30 秒)。 因此,Kubernetes 不会等待这些完成。 宽限期结束,则直接进入下一步。 所以正确设置宽限期的值非常重要。
  5. SIGKILL 信号发送到 pod,并且 pod 被删除。 如果宽限期过后容器仍在运行,则通过 SIGKILL 强制删除 pod,终止结束。
spec:
  containers:
  - name: "example-container"
    image: "example-image"
    lifecycle:
      preStop:
        exec:
          command: ["sh", "-c", "sleep 10"]

配置 preStop 主要是为了在关闭 Pod 之前,希望确保正在处理的请求能够完成,以避免数据丢失或中断服务。

如果使用 SpringBoot 2.3及以上版本,建议配合 SpringBoot 的优雅停机使用,在配置文件 application.properties 中配置:

server.shutdown=graceful
management.endpoints.web.exposure.include=*

总结

在Kubernetes环境下实现Spring + Dubbo应用的优雅停机是确保服务高可用性的重要一环。通过合理配置Kubernetes探针和Dubbo的关闭扩展点,以及设置合适的terminationGracePeriodSeconds,可以确保服务在关闭时不会丢失请求,保证了系统的稳定性和可靠性。

分享内容