参考文档
掌握SpringBoot-2.3的容器探针:基础篇
Spring Boot 2.3+ Liveness 和 Readness 接口使用

1. 存活探针

  1. kubernetes 的探针涉及的内容是很多的,这里只提和 SpringBoot 相关的部分;

  2. kubelet 使用存活探针 livenessProbe 来知道什么时候要重启容器;

  3. 下图是 kubernetes 官网的存活探针示例,几个关键参数已经做了详细说明:

    在这里插入图片描述

    1. 可见如果我们的 SpringBoot 应用发布到 kubernetes 环境,只要应用还健康,livenessProbe 对应的地址就要能响应 200-400 的返回码;

2. 就绪探针

  1. 有时候,应用程序会暂时性的不能提供通信服务。
    例如,应用程序在启动时可能需要加载很大的数据或配置文件,或是启动后要依赖等待外部服务。在这种情况下,既不想杀死应用程序,也不想给它发送请求。Kubernetes 提供了就绪探测器来发现并缓解这些情况。容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量。
  2. 就绪探测器的配置和存活探测器的配置相似,唯一区别就是要使用 readinessProbe字段,而不是 livenessProbe 字段;
  3. 简单的说,就绪探针正常的容器,k8s 就认为是可以对外提供服务的,相应的请求也会被调度到该容器上来;

3. Actuator

简单来说,actuator 是用来帮助用户监控和操作 SprinBoot 应用的,这些监控和操作都可以通过 http 请求实现,如下图,http://localhost:8080/actuator/health 地址返回的是应用的健康状态:

在这里插入图片描述

3.1 所需依赖

plugins {
    id 'org.springframework.boot' version '2.3.2.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
}
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

3.2 分组

在 SpringBoot-2.3 版本中,actuator 新增了分组的概念,默认分为 liveness 和 readness 两个组,需显式指定后才能使用,两个地址:/actuator/health/liveness/actuator/health/readiness,前者用作kubernetes 的存活探针,后者用作 kubernetes 的就绪探针;/actuator/health 接口包含所有的指标

在这里插入图片描述

查看当前应用支持的指标,可以设置 management.endpoint.health.show-details=always后从 /actuator/health 接口获取。

先指定 readness 指标,之后可以将剩余的所有指标设置为 liveness 的指标

management.endpoint.health.show-details=always
management.endpoint.health.group.readiness.include=ping
management.endpoint.health.group.liveness.include=*
management.endpoint.health.group.liveness.exclude=${management.endpoint.health.group.readiness.include}

3.3 测试

3.3.1 health

curl http://localhost:8080/actuator/health
{
    "status": "UP",
    "components": {
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 499963174912,
                "free": 380364800000,
                "threshold": 10485760,
                "exists": true
            }
        },
        "livenessStateProbeIndicator": {
            "status": "UP"
        },
        "ping": {
            "status": "UP"
        },
        "readinessStateProbeIndicator": {
            "status": "UP"
        }
    },
    "groups": [
        "liveness",
        "readiness"
    ]
}

3.3.2 readiness

curl http://localhost:8080/actuator/health/readiness
{
    "components": {
        "ping": {
            "status": "UP"
        }
    },
    "status": "UP"
}

3.3.3 liveness

curl http://localhost:8080/actuator/health/liveness
{
    "components": {
        "custom": {
            "details": {
                "Status": "Health"
            },
            "status": "UP"
        },
        "diskSpace": {
            "details": {
                "exists": true,
                "free": 380286464000,
                "threshold": 10485760,
                "total": 499963174912
            },
            "status": "UP"
        }
    },
    "status": "UP"
}

3.4 自定义检查项

自定义一个新的 HealthIndicator,添加到相应的分组即可, 默认名为类名前缀(第一个字母小写)

@Component
public class CustomHealthIndicator implements HealthIndicator {

    private boolean health = true;

    @Override
    public Health health() {
        if (health) {
            return Health.up().withDetail("Status", "Health").build();
        }
        return Health.down().withDetail("Status", "Not Health").build();
    }

    public void setHealth(boolean health) {
        this.health = health;
    }
}

测试

添加到分组

management.endpoint.health.group.readiness.include=ping,custom
curl http://localhost:8080/actuator/health/readiness
{
    "components": {
        "custom": {
            "details": {
                "Status": "Health"
            },
            "status": "UP"
        },
        "ping": {
            "status": "UP"
        }
    },
    "status": "UP"
}

4. SpringBoot 对容器环境的判断

SpringBoot 为 kubernetes 提供了两个 actuator 项,但是那些并未部署在 kubernetes 的 SringBoot 应用呢?用不上这两项也要对外暴露这两个服务地址吗?

SpringBoot 判断是否是 kubernetes 环境的逻辑很简单:是否有*_SERVICE_HOST*_SERVICE_PORT 这两个环境变量。

熟悉kubernetes的读者,应该会想起 KUBERNETES_SERVICE_HOST 和 KUBERNETES_SERVICE_PORT,这是 k8s 给 pod 中配置的环境变量,看来 SpringBoot 也是针对 k8s 的这个规则来判定是否是容器环境的。

那非 kubernetes 环境怎么开启探针呢。

  1. 加上上述两个环境变量。
  2. 添加配置 management.health.probes.enabled=true

5. 探针的状态

存活探针有两个状态

  1. CORRECT 表示应用运行中并且内部状态正常
  2. BROKEN 表示应用运行中并且内部是 BROKEN 状态

就绪探针状态

  1. ACCEPTING_TRAFFIC 表示应用可以对外提供服务
  2. REFUSING_TRAFFIC 表示应用无法对外提供服务;

在 SpringBoot 启动过程中,应用、存活探针、就绪探针三者状态对应关系如下图:

在这里插入图片描述

在 SpringBoot 停止过程中,应用、存活探针、就绪探针三者状态对应关系如下图:

在这里插入图片描述

获取状态

@Resource
ApplicationAvailability applicationAvailability;

public void getStatus(){
    LivenessState livenessState = applicationAvailability.getLivenessState();
    ReadinessState readinessState = applicationAvailability.getReadinessState();
}

监听状态

@Component
public class StateListener {

    @EventListener
    public void onStateChange(AvailabilityChangeEvent<?> event) {
        event.getState();
    }
}

修改状态

@Resource
ApplicationEventPublisher eventPublisher;

public void changeState() {
    AvailabilityChangeEvent.publish(eventPublisher, this, LivenessState.BROKEN);
    AvailabilityChangeEvent.publish(eventPublisher, this, ReadinessState.REFUSING_TRAFFIC);
}