1. 健康检查概述

聊容灾之前,咱们得先把“健康检查”这事儿聊透。我刚开始做运维那会儿,觉得健康检查就是个“ping”一下的事儿。直到有一次线上故障,数据库主库挂了整整15分钟,我们竟然没人知道。嗯,从那以后,我才真正开始重新审视什么是健康检查。

1.1 什么是健康检查

说白了,健康检查就是一套自动化的“望闻问切”流程。它定期去探测你的系统、服务或实例,看它们到底还能不能正常工作。

你想想看,一个服务进程还活着,不代表它就能正常响应请求。我在项目中遇到过不少这样的情况:进程在,端口也在,但业务已经慢到无法忍受了。这时候,简单的“ping端口”就完全不管用。

所以,健康检查要做的,是确认三个层次的问题:

  • 存活检查:进程还在不在?端口还开着没?
  • 就绪检查:服务有没有准备好接收流量?
  • 业务检查:核心业务接口能不能在预期时间内返回正确结果?
我的习惯:我会把健康检查设计成“从外到内”的三层结构。第一层是负载均衡层面的探测,第二层是容器调度平台的探针,第三层是应用内部的健康报告接口。三层联动,基本能覆盖90%的异常场景。

1.2 健康检查的目的与重要性

为什么要费这么大劲做健康检查?直接写个脚本监控CPU内存不行吗?

我个人的理解是,健康检查解决了一个最核心的问题:快速确认系统是否具备对外提供服务的能力。它不是为了发现问题,而是为了在问题发生的那一刻,立刻触发决策——到底是继续用这台机器,还是把它摘掉,换一台干净的上来。

我梳理了一下,健康检查的目的可以归纳为三点:

  1. 服务摘流量:一旦检查发现实例不健康,立刻通知负载均衡把流量切走,防止故障扩散。我曾经因为漏配了一个健康检查,导致一台内存泄漏的服务器继续接收请求,最终把整个集群拖垮了。
  2. 触发恢复:通知编排平台重启容器或重建实例,把不健康的状态重置掉。
  3. 辅助决策:在发布、扩缩容、容灾切换的瞬间,健康检查结果是判断“是否成功”的唯一标准。
你一定要记住:健康检查不是监控。监控告诉你“现在出问题了”,而健康检查决定“接下来该怎么办”。这两者的时效性完全不同。健康检查的响应时间通常被要求在秒级甚至毫秒级,而监控可以容忍分钟级的数据聚合。

1.3 健康检查的分类

为了把这些概念讲明白,我画了一张结构图,把健康检查的分类体系呈现出来。

健康检查分类体系 健康检查 ① 按检查层次 ② 按检查主体 ③ 按触发方式 存活 就绪 业务自定义检查 TCP探查 HTTP探查 gRPC/自定义协议 被动检查 主动检查 设计建议 1. 三层检查必须组合使用。单靠存活检查,无法感知业务缓慢。 2. HTTP探查是最通用的选择,尽量暴露 /health 端点,返回 JSON 格式的状态。 3. 主动检查用于上游依赖的预判,被动检查用于真实流量的验证。 4. 我曾经只用TCP存活检查,导致某次慢SQL雪崩无人发现—— 从那以后,所有核心服务必须通过业务自定义检查才能上线。

从上面的图你能看出来,健康检查可以从三个维度来分类。在实际工作中,我们往往需要把它们组合起来用。我来详细说说每一类。

按检查层次来分

这是最实用的分类方式。我一般会把它做成一个金字塔:

  • 存活检查(Liveness Probe):最简单的逻辑。进程活着吗?端口通着吗?它只告诉你“死没死”。如果挂了,就重启。
  • 就绪检查(Readiness Probe):服务有没有能力处理请求?比如,应用刚启动完,但缓存还没预热。这时候存活检查是通的,但就绪检查应该返回失败。流量就不会打进去。
  • 业务自定义检查:这是我最看重的。比如数据库连接池里还能不能拿到连接?核心API的P99延迟是否超过了100ms?我曾经见过一个案例:缓存集群里的节点全挂了,但每个节点上的sentinel进程还活着,存活检查全绿,业务已经瘫痪了5分钟。原因就是没人做业务层面的检查。

按检查主体来分

这决定了你怎么去“问”系统:

检查方式 原理 适用场景 缺点
TCP探查 尝试建立TCP连接,成功即视为健康 基础网络连通性、后端服务端口检查 无法感知业务状态,连接成功后什么都不代表
HTTP探查 发送GET/POST请求,根据状态码判断 Web服务、API网关、微服务 需要应用暴露健康端点,增加一点性能开销
gRPC/自定义协议 通过自定义接口或gRPC health协议交互 内部微服务体系、长连接网关 实现较复杂,需要SDK支持

我的经验:我通常把HTTP探查作为第一选择。因为它最灵活,健康端点里甚至可以返回“整体健康度评分”。我曾经在一个高并发项目里,把健康检查设计成“累进式检查”——前两次快速返回200,第三次全量检查并附带慢查询检测。这样既保证了探测的轻量,又能在需要时深入检查。

按触发方式来分

这一点容易被忽视,但容灾场景下特别重要:

  • 被动检查:流量进来后,服务才返回状态。比如客户端请求超时,就认为实例不健康。这种方式有风险——脏流量可能已经进入系统了。
  • 主动检查:由监控系统或负载均衡器主动发请求去检测实例状态。这样能在流量进入之前就做出决策。容灾切换必须用主动检查,被动检查只能作为补充。

你想想看,容灾切换的瞬间,我们需要的是一个“确定性”——这台机器到底能不能接流量。主动检查能给出这个确定性。我建议所有核心服务都把主动检查作为容灾切流的前提条件。

避坑指南:我曾经在某个项目中,把健康检查的间隔设成了60秒。容灾演练的时候,主库挂了,负载均衡等了50秒才探测到,然后触发切换。你知道这50秒发生了什么吗?业务层已经因为连接超时开始报错了。现在我把主动检查的间隔控制在5秒以内,超时时间不超过2秒。记住,健康检查的探测间隔和超时时间,直接决定了你的RTO。