防止在所有当前请求完成之前关闭Spring Boot应用程序

slo*_*wko 6 java docker spring-boot kubernetes spring-boot-actuator

我们有一个Spring Boot(2.0.4)应用程序,它公开了许多端点,其中一个端点使客户端可以检索有时非常大的文件(约200 GB)。该应用程序通过配置了滚动更新策略的Kubernetes部署在Pod中公开。

当我们通过将映像设置为最新版本来更新部署时,吊舱会被破坏,新的吊舱会旋转。我们的服务可满足新要求。但是,当前的请求可能并且确实会被切断,这对于下载非常大文件的客户端来说可能会很烦人。

我们可以在部署规范中配置Container Lifecycle Pre-Stop挂钩,以在通过其PID发送关闭信号给应用之前注入暂停。这有助于防止任何新流量流向已设置为“终止”的Pod。有没有一种方法可以暂停应用程序关闭过程,直到所有当前请求都已完成(这可能需要数十分钟)?

这是我们在Spring Boot应用程序中尝试过的方法:

  • 实现一个关闭侦听器ContextCloseEvents; 不幸的是,我们无法可靠地检索活动请求列表。在关机过程的此阶段,任何可能有用的执行器指标均不可用。

  • 通过实施HttpSessionListener和覆盖sessionCreated/Destroy方法来更新计数器来对活动会话进行计数。失败是因为方法没有在单独的线程上调用,所以始终在关闭侦听器中报告相同的值。

我们应该尝试其他策略吗?从应用程序本身或容器中,还是直接通过Kubernetes资源描述符?建议/帮助/指针将不胜感激。

编辑:我们管理集群,因此我们仅尝试通过修改的Pod规范在对部署进行托管更新期间减轻当前连接的客户端的服务中断

slo*_*wko 4

我们结合了上述方法来解决我们的问题。

  • 将终止宽限期秒数增加到我们期望在生产中看到的绝对最大值
  • 添加了 livenessProbe 以防止 Traefik 过早路由到我们的 Pod
  • 引入了一个预停止钩子,注入暂停并调用监控脚本:
    1. 使用集群 Traefik 服务的外部地址监视 netstat 是否已建立与进程 (pid 1) 的连接
    2. 发送 TERM 到 pid 1

请注意,因为我们从监控脚本将 TERM 发送到 pid 1,所以 Pod 将在此时终止,并且 TerminationGracePeriodSeconds 永远不会被命中(它是作为预防措施而存在的)

这是脚本:

#!/bin/sh

while [ "$(/bin/netstat -ap 2>/dev/null | /bin/grep http-alt.*ESTABLISHED.*1/java | grep -c traefik-ingress-service)" -gt 0 ]
do
  sleep 1
done

kill -TERM 1
Run Code Online (Sandbox Code Playgroud)

这是新的 pod 规格:

containers:
  - env:
    - name: spring_profiles_active
      value: dev
    image: container.registry.host/project/app:@@version@@
    imagePullPolicy: Always
    lifecycle:
      preStop:
        exec:
          command:
          - /bin/sh
          - -c
          - sleep 5 && /monitoring.sh
    livenessProbe:
      httpGet:
        path: /actuator/health
        port: 8080
      initialDelaySeconds: 60
      periodSeconds: 20
      timeoutSeconds: 3
    name: app
    ports:
    - containerPort: 8080
    readinessProbe:
      httpGet:
        path: /actuator/health
        port: 8080
      initialDelaySeconds: 60
    resources:
      limits:
        cpu: 2
        memory: 2Gi
      requests:
        cpu: 2
        memory: 2Gi
  imagePullSecrets:
  - name: app-secret
  serviceAccountName: vault-auth
  terminationGracePeriodSeconds: 86400
Run Code Online (Sandbox Code Playgroud)