k01.jpg

Spring Boot 是常用 Java 微服务框架之一。Spring Cloud 拥有一组丰富的、良好集成的 Java 类库,用于应对 Java 应用程序堆栈中发生的运行时问题;而 Kubernetes 则提供了丰富的功能集来运行多语言微服务。这些技术彼此互补,为 Spring Boot 应用程序提供了强大的平台。

本文不是讲述如何将Spring Boot 程序部署到Kubernetes中,网上已经有大量的部署实践文章,大家有兴趣的可以查阅。主要讲述Spring Boot社区为了进一步简化和规范Spring Boot on k8s而做出的一些功能增强。大家完全可以将这些新功能实践到自己项目中。

Liveness 和 Readiness

首先我们简单介绍一下,kubernetes 中 Liveness 和 Readiness的含义。

在Kubernetes中,Liveness 和 Readiness代表了应用程序状态的各个方面。

应用程序的Liveness状态表明内部状态是否有效,如果Liveness 失败,则意味着应用程序本身处于故障状态并且无法从中恢复,在这种情况下,最佳的操作方法是重新启动应用程序例如,如果本地缓存已损坏且无法修复,则依赖本地缓存的应用程序应使其Liveness检测失败。

Readiness状态告诉应用程序是否准备好接受客户端请求;如果Readiness状态尚未就绪,则Kubernetes不应将流量路由到该实例;如果应用程序正忙于处理任务队列,则它可以将自己声明为繁忙,直到其执行负载可以再次管理。

那么接下来我们看下Spring Boot怎么支持Liveness 和 Readiness。

Liveness 和 Readiness 成为 Spring Boot 核心概念

Liveness 和 Readiness概念不仅适用于Kubernetes,而且无论部署平台如何,它们通常都有用。引入了LivenessStateReadinessState,它们是这些概念的不可变表示形式。您可以随时从ApplicationAvailability中获取它们:

// Available as a component in the application context
ApplicationAvailability availability;

LivenessState livenessState = availabilityProvider.getLivenessState();
ReadinessState readinessState = availabilityProvider.getReadinessState()

通过轮询,获取应用程序的状态是不完整的。只有应用程序知道其生命周期(启动,关闭),或者可以提供有关运行时错误的上下文(在处理任务时以中断状态结束)。Spring Boot应用程序上下文在应用程序的生命周期内发布这些事件,您的应用程序代码也应对此做出适配。

这就是为什么我们选择使用Spring Application Event模型来更改可用性状态并监听更新的原因:

/**
 * Component that checks that the local cache is in a valid state.
 */
@Component
public class LocalCacheVerifier {

    private final ApplicationEventPublisher eventPublisher;

    public LocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    public void checkLocalCache() {
        try {
            //...
        }
        catch (CacheCompletelyBroken ex) {
            AvailabilityChangeEvent.publish(this.eventPublisher, LivenessState.BROKEN);
        }
    }

}

组件还可以使用@EventListener监听这些事件(或通过实现ApplicationListener)。请查阅参考文档以获取更多信息。

该支持直接与spring-boot模块一起提供,并已为所有Spring Boot应用程序激活;这使其可用于所有类型的应用程序(Web,批处理等),并允许您实现不一定与HTTP绑定的探针。

使用Spring Boot Actuator公开Kubernetes探针

可能会对一个非常常见的用例感兴趣:在Kubernetes上部署Web应用程序并配置HTTP探针,将Spring Boot Actuator依赖项添加到您的应用程序是唯一的要求!Actuator将使用Health支持配置Liveness和Readiness HTTP探针。

Actuator将从ApplicationAvailability收集“Liveness”和“Readiness”信息,并将其用于专用的健康指标:LivenessStateHealthIndicatorReadinessStateHealthIndicator。这些指标将暴露在"/actuator/health"路径上。如果需要进一步了解“Liveness”和“Readiness”信息,可以通过"/actuator/health/liveness""/actuator/health/readiness"访问获得。

在Kubernetes上运行的应用程序将显示以下运行状况报告:

// http://localhost:8080/actuator/health
// HTTP/1.1 200 OK

{
  "status": "UP",
  "components": {
    "diskSpace": {
      "status": "UP",
      "details": { //...
      }
    },
    "livenessProbe": {
      "status": "UP"
    },
    "ping": {
      "status": "UP"
    },
    "readinessProbe": {
      "status": "UP"
    }
  },
  "groups": [
    "liveness",
    "readiness"
  ]
}

调用Liveness组时,Kubernetes将获得以下信息:

// http://localhost:8080/actuator/health/liveness
// HTTP/1.1 200 OK

{
  "status": "UP",
  "components": {
    "livenessProbe": {
      "status": "UP"
    }
  }
}

标记为未就绪的应用程序将为“就绪”组报告以下内容:

// http://localhost:8080/actuator/health/readiness
// HTTP/1.1 503 SERVICE UNAVAILABLE

{
  "status": "OUT_OF_SERVICE",
  "components": {
    "readinessProbe": {
      "status": "OUT_OF_SERVICE"
    }
  }
}

HTTP探针仅针对Kubernetes上运行的应用程序进行配置。您可以通过使用management.health.probes.enabled = true配置属性手动启用探针在本地进行尝试。由于探针是运行状况组,因此您将获得许多其他功能例如配置HTTP状态映射器,安全性,详细信息可见性…

当然,您可以将其他运行状况指示器配置为探针的一部分,以检查外部系统的状态:数据库,Web API,共享缓存。给定现有的CacheCheckHealthIndicator,您可以使用以下方法扩充活动性探针:

management.endpoint.health.group.liveness.include=livenessProbe,cacheCheck

Graceful shutdown

由于运行在Kubernetes中的Pod存在动态的特性,这就要求我们的应用程序要做相应的适配。优雅关闭就是其中重要的一个。需要应用程序监听SIGTERM信号,停止接受新的链接,处理已有的链接等等。此时框架提供了该功能,那么我们的业务代码可以更加简单。

下面讲了Spring boot 框架是怎么实现的?

所有四个嵌入式Web服务器(Jetty,Reactor Netty,Tomcat和Undertow)以及基于响应的和基于Servlet的Web应用程序都支持正常关闭。启用后,应用程序关闭将包括可配置持续时间的宽限期。宽限期内,现有请求将被允许完成,但新请求将被禁止。不允许新请求的确切方式因所使用的Web服务器而异,Jetty,Reactor Netty和Tomcat将停止接受请求Undertow将接受请求,但会立即以服务不可用(503)响应进行响应。

正常关闭是在应用程序关闭处理期间以及销毁任何Bean之前的第一步,这确保了允许在运行中请求完成时发生的任何处理都可以使用这些Bean。 配置server.shutdown.grace-period 属性,如以下示例所示:

server.shutdown.grace-period=30s

理论上该值应该和Kubernetes 部署yaml中的terminationGracePeriodSeconds设定的值相等。

当然除了这两个比较重要的特性,还有Docker镜像创建这个点,感兴趣的可以去了解一下,这里不再阐述。


iyacontrol
1.4k 声望2.7k 粉丝

专注kubernetes,devops,aiops,service mesh。