🌟 一、核心目标:让 Spring Boot 应用"懂"Kubernetes
Kubernetes(K8s)是一个容器编排系统。它需要知道:
- 这个应用是否还活着? → 用 Liveness Probe
- 这个应用是否准备好接收流量? → 用 Readiness Probe
- (可选)这个应用启动是否完成? → 用 Startup Probe
Spring Boot Actuator 现在 原生支持这些探针 ,无需你手动写 /health/liveness 接口。
🔌 二、Spring Boot 是怎么做的?(自动集成)
✅ Spring Boot 自动做了三件事:
| 功能 | 实现方式 |
|---|---|
| 1. 管理应用的"可用性状态" | 内置 ApplicationAvailability 接口 |
| 2. 提供 Liveness 检查 | LivenessStateHealthIndicator |
| 3. 提供 Readiness 检查 | ReadinessStateHealthIndicator |
这两个健康检查会自动出现在:
/actuator/health
同时,还会单独暴露为两个独立端点:
| 探针 | 对应端点 |
|---|---|
| Liveness Probe | /actuator/health/liveness |
| Readiness Probe | `/actuator/health/readiness`` |
✅ 这两个端点其实是 Health Group(健康分组),我们在上一节讲过。
📡 三、K8s 配置示例:如何使用这些探针?
你只需要在 deployment.yaml 中这样配置:
yaml
spec:
containers:
- name: myapp
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 1
K8s 的 kubelet 会定期调用这些接口,并根据返回结果采取行动。
🧩 四、两个探针的区别:Liveness vs Readiness
这是最关键的部分!
| 对比项 | Liveness Probe(存活探针) | Readiness Probe(就绪探针) |
|---|---|---|
| 目的 | 检查应用是否"卡死" | 检查应用是否"准备好"处理请求 |
| 失败后果 | 重启容器 ⚠️ | 停止转发流量,但不重启 |
| 何时失败 | 应用启动太慢、死锁、OOM | 正在初始化、数据库未连上 |
| 能否自定义 | ✅ 可配置 | ✅ 可配置 |
| 建议检查什么 | 只检查应用内部状态(不要查外部服务!) | 可选择性检查外部依赖(需谨慎) |
⚠️ 五、关键原则:Liveness 探针不要检查外部系统!
❌ 错误做法:
yaml
management:
endpoint:
health:
group:
liveness:
include: db,redis,livenessState
如果数据库挂了,所有实例的 Liveness 都失败 → K8s 会重启所有实例 → 导致雪崩式重启!
✅ 正确做法:
yaml
management:
endpoint:
health:
group:
liveness:
include: livenessState # 只检查内部状态
✅ Liveness 只关心:Spring 容器是否启动成功、线程是否卡死、内存是否溢出。
✅ 六、Readiness 探针:可以检查外部依赖,但要小心
场景分析:
| 外部依赖类型 | 是否该加入 Readiness? | 说明 |
|---|---|---|
| 数据库(共享) | ❌ 不推荐 | 所有实例共用,一旦挂掉,所有实例都 unready → 整个服务下线 |
| 缓存(如 Redis) | ❌ 不推荐 | 同上,可能造成服务整体不可用 |
| 某个本地文件/端口 | ✅ 推荐 | 只影响当前实例,比如文件锁、端口占用 |
| 有降级机制的服务 | ✅ 可以不加 | 比如用了 Hystrix 断路器,即使依赖挂了也能返回默认值 |
示例配置:
yaml
management:
endpoint:
health:
group:
readiness:
include: readinessState,diskspace
exclude: db,redis
✅ 这样即使数据库暂时连不上,只要应用本身启动了,K8s 仍可转发流量,由应用内部处理降级。
🔄 七、应用生命周期与探针状态的对应关系
Spring Boot 会根据应用的启动和关闭过程,自动更新 Liveness 和 Readiness 状态。
🚀 应用启动过程:
| 阶段 | Liveness State | Readiness State | 含义 |
|---|---|---|---|
| 1. Starting(刚开始启动) | BROKEN |
REFUSING_TRAFFIC |
K8s 可能会重启(如果超时) |
| 2. Started(上下文加载完成) | CORRECT |
REFUSING_TRAFFIC |
应用在做初始化任务,不接流量 |
| 3. Ready(准备就绪) | CORRECT |
ACCEPTING_TRAFFIC |
可以接收外部请求了 ✅ |
✅ 这意味着:即使 Spring 容器启动了,但你的
@PostConstruct或异步任务还没完成,K8s 也不会把流量打过来!
🛑 应用关闭过程:
| 阶段 | Liveness State | Readiness State | 含义 |
|---|---|---|---|
| 1. Running | LIVE |
READY |
正常运行 |
| 2. Graceful Shutdown(优雅关闭) | LIVE |
UNREADY |
停止接收新请求,但处理完正在执行的 |
| 3. Shutdown Complete | BROKEN |
UNREADY |
容器即将退出 |
✅ 这样可以实现零停机部署(Rolling Update)!
🧪 八、Startup Probe:解决启动慢的问题
有时候应用启动要几分钟(比如加载大缓存、预热模型),而 Liveness 探针默认 30 秒就超时 → 会被误杀。
解决方案:使用 startupProbe
yaml
startupProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
failureThreshold: 60 # 最多等待 60 次
periodSeconds: 10 # 每 10 秒检查一次 → 最多等 10 分钟
timeoutSeconds: 5
✅ 一旦 startupProbe 成功,K8s 就会启用 livenessProbe 和 readinessProbe。
⚠️ 九、重要提醒:Actuator 在独立管理端口时的问题
如果你配置了:
yaml
management:
server:
port: 8081
那么 /actuator/health/readiness 是在 8081 端口,而主应用在 8080。
⚠️ 问题:8081 健康 ≠ 8080 健康!
可能主应用(8080)已经卡死,但 Actuator(8081)还能响应 → K8s 认为它"健康",继续转发流量 → 请求失败。
✅ 建议:
- 不要用独立管理端口,除非你有特殊安全需求。
- 或者,确保
/actuator/health/readiness的检查能反映主应用的真实状态。
🧩 十、如何自定义 Readiness 检查?
你可以把自定义的健康检查加入 Readiness 组:
yaml
management:
endpoint:
health:
group:
readiness:
include: readinessState,customCheck,diskspace
然后写一个 CustomCheckHealthIndicator:
java
@Component
public class CustomCheckHealthIndicator implements HealthIndicator {
@Override
public Health health() {
if (isCustomSystemReady()) {
return Health.up().build();
} else {
return Health.outOfService().build();
}
}
}
📊 总结:一张表看懂核心概念
| 概念 | 作用 | 是否重启 | 建议检查内容 |
|---|---|---|---|
| Liveness Probe | 应用是否"卡死" | ✅ 会重启 | 只检查内部状态(如内存、线程) |
| Readiness Probe | 是否准备好接流量 | ❌ 不重启 | 可检查本地资源(磁盘、端口),慎查共享外部服务 |
| Startup Probe | 启动是否完成 | ✅ 会重启 | 用于启动时间长的应用 |
💡 实际建议
-
开启这两个探针:
yamlmanagement: endpoint: health: probes: enabled: true -
K8s 配置中使用
/actuator/health/liveness和/actuator/health/readiness -
不要让 Liveness 依赖数据库、Redis 等外部服务
-
利用 Readiness 实现优雅上下线
-
长启动应用一定要配
startupProbe
这套机制是 Spring Boot 迈向 云原生(Cloud Native) 的重要一步,让你的应用真正"感知生命周期",而不仅仅是一个黑盒容器。
如果你需要,我可以给你一个完整的 application.yml + deployment.yaml 示例,展示如何在生产环境中配置这些探针。