健康检查需精细调优,关键在start-period、超时控制和检查逻辑合理性:start-period避免冷启动误判,命令级超时防阻塞,检查须验证业务可达性而非仅端口监听。
健康检查不是“配了就完事”的开关,而是需要结合应用行为、启动节奏和依赖关系精细调优的运行时保障机制。真正起作用的配置,往往藏在 start-period、超时控制 和 检查逻辑合理性 这三个关键点里。
如何让健康检查真正反映服务可用性
只检查端口监听或进程存在,等于没查——健康检查必须验证业务可达性。比如:
- Web 服务:访问
/health或/actuator/health,且要求返回 HTTP 200 + 响应体含"status":"UP" - 数据库(PostgreSQL):用
pg_isready -U user -d dbname,它比curl更精准,不依赖网络服务暴露 - 消息队列(Redis):执行
redis-cli -h localhost ping | grep -q 'PONG',避免因连接池未建好误判 - Java 应用:优先检查
/actuator/health,而非/;若含 DB 依赖,确保该端点已聚合数据库连通性
start-period 不是可选项,而是慢启动服务的生命线
Spring Boot、PostgreSQL、Elasticsearch 等服务冷启动常需 30–120 秒。若未设 start-period,Docker 会在容器刚 run 起来几秒内就开始健康检查,必然失败并计入重试,最终标记为 unhealthy。
-
start-period=60s表示:启动后前 60 秒内,所有检查失败都不计数,状态保持starting - 这个时间必须 ≥ 应用完成初始化、建立连接、加载缓存、监听端口的总耗时
- 实测建议:Spring Boot 服务设
120s,PostgreSQL 设45s,Elasticsearch 设90s
命令级超时必须显式控制,不能依赖 Docker timeout
Docker 的 --timeout 只限制命令启动后多久杀掉进程,但若命令本身卡住(如 curl 等 DNS 解析、TCP 握手),可能根本没触发 Docker 超时——导致后续检查被阻塞、状态长时间滞留 starting 或假死。
- 错误写法:
curl http://localhost:8080/health(无超时,可能 hang 住) - 正确写法:
curl -f --max-time 3 http://localhost:8080/health || exit 1 - 对
pg_isready加-t 5(单位秒),redis-cli加-t 2 - Shell 脚本中务必用
set -e,确保任意子命令失败立即退出,不掩盖错误
四步定位健康检查为何总失败
别猜,按顺序查:
-
看状态:运行
docker inspect myapp | grep -A 10 "Health",确认当前是starting、unhealthy还是healthy,以及最近一次检查的ExitCode和Output -
进容器手动跑:执行
docker exec -it myapp sh,然后复现健康检查命令(如curl -v --max-time 3 http://localhost:8080/health),观察是否超时、DNS 失败、连接拒绝或返回非 200 -
查依赖就绪状态:如果检查依赖数据库,先确认
db容器是否已service_healthy;用docker logs db看 PostgreSQL 是否已完成 initdb 并 ready for connections -
验证路径与权限:Alpine 镜像默认无
curl,BusyBox 版curl不支持-f;确认检查脚本有执行权限(chmod +x /health.sh),且路径在容器内真实存在











