从一个故障场景说起
假设你有一组后端服务节点,它们共享同一个 Redis 集群作为缓存层。某天这个 Redis 集群出现了短暂的网络分区,持续约 30 秒。
在百万 QPS 系统中,你的健康检查可能只是一个简单的 /health 接口,它检查的是进程能不能正常响应。Redis 出了问题,但进程本身还活着,健康检查照样返回 200,流量继续正常分配。虽然缓存失效导致请求变慢甚至部分失败,但至少系统还在运转,自愈之后恢复正常。
现在同样的场景放到千万 QPS 系统中。你已经上了深度健康检查,节点会检查 Redis 依赖是否正常。结果是,所有节点同时检测到 Redis 不可达,同时报告自己不健康,负载均衡器在几秒内将全部节点摘除。
Redis 故障 30 秒,你的服务却完全中断了 30 秒。原本只是缓存层的问题,却因为健康检查的深度反而被放大成了全站不可用。
这就是深度健康检查的核心矛盾:检查得越深入,越可能因为共享依赖的故障而触发大面积误摘,造成比原始故障更严重的后果。
理解这个矛盾,是理解千万 QPS 健康检查架构设计的关键。
健康检查的演进:从判断死活到评估健康度
从十万 QPS 到千万 QPS 的演进过程中,健康检查经历了三个阶段,每个阶段要解决的核心问题截然不同。

需要说明的是,每个阶段的跃迁并不是前一阶段不行了,而是 规模增长暴露出了前一阶段无法覆盖的盲区。
- 在十万 QPS 量级,集群节点有限,冗余充足,即使某个节点半死不活,对整体影响可控,端口存活检查就够用了。
- 到了百万 QPS 量级,节点增多,一个假活节点持续吃掉大量请求却返回错误或超时,影响面开始变得不可忽视。接口探测解决了进程活着但服务不可用的盲区,成为这个量级的标准做法。
- 到了千万 QPS 量级,接口能响应本身也不再足够。一个节点的 /health 接口返回 200,只能证明它能处理一个轻量探测请求,无法证明它的缓存连通性正常、数据库连接池未耗尽、当前负载还有余力承接更多流量。节点规模到了成百上千台,任何一批节点的亚健康状态如果不能被感知,就会持续拉低整体服务质量。
深度健康检查的三个维度
深度健康检查的核心是将健康状态从二元判定扩展为多维度的综合评估,主要包含三个维度。

3.1 接口探测的深化
深度健康检查中的接口探测,不再只是返回 200 就算健康,而是对响应做更细粒度的校验。
- 响应内容校验:健康检查接口返回结构化的状态报告,包含各子系统的状态标识。调用方需要解析响应体中的关键字段,只有所有关键子系统状态正常时才判定为健康。这比单纯检查 HTTP 状态码多了一层语义校验。
- 响应时间的相对评估:同样返回 200,一个节点 2ms 返回、另一个 200ms 返回,背后的含义可能完全不同。但响应时间评估不适合设置绝对阈值,不同业务场景下正常的响应时间差异很大。更合理的做法是基于同组节点的相对比较:如果某个节点的响应时间显著偏离同组均值,往往意味着它的某个依赖或资源已经出现性能退化。
3.2 依赖检查
依赖检查是深度健康检查与简单接口探测的核心区别,也是架构复杂度最高的部分。
一个后端服务节点通常依赖缓存、数据库、消息队列、下游微服务等多个组件。任何一个关键依赖出现问题,都可能导致节点虽然活着,但无法完成业务请求。依赖检查的思路是:在健康检查接口中主动探测各关键依赖的可用性,并将结果纳入健康状态的综合判定。
依赖检查中最关键的设计决策是对依赖的分级。

- 关键依赖:缺失后业务请求完全无法完成的依赖(如核心数据库)。关键依赖不可达时,节点应被判定为不健康。
- 非关键依赖:缺失后服务可以降级运行的依赖(如缓存,缓存不可用时可以回源数据库,虽然慢但还能用)。非关键依赖不可达时,节点应被标记为亚健康,降低流量权重而非直接摘除。
这个分级看似简单,但在实践中需要业务方逐一梳理并明确,同一个组件在不同业务场景下可能属于不同的级别。
3.3 自定义检查
自定义检查是最灵活的维度,允许业务方根据自身特性定义健康判定条件。常见的方向包括:
- 负载水位:CPU、内存、连接数等资源使用率。一个 CPU 已达 90% 的节点,即使依赖全部正常,也不应该继续接收与其他节点等比例的流量。负载水位的价值不在于判断健不健康,而在于判断还有没有余力。
- 业务指标:近一段时间窗口内的错误率、P99 延迟等。业务层面的信号往往比基础设施指标更直接反映服务能力,一个节点的 CPU 和内存都正常,但错误率突然升高,往往意味着出现了基础指标无法捕捉的问题。
- 资源余量:磁盘空间、文件描述符、线程池余量等。这些资源的耗尽通常是渐进式的,一旦到达临界点就可能导致突发故障。在资源余量不足时提前降低流量权重,是一种预防性的保护措施。
多级健康状态:从非黑即白到灰度判定
深度健康检查能提供多维度的信息,自然引出一个设计问题:如何用这些信息驱动流量调度?
在百万 QPS 量级,健康和不健康两个状态通常够用。但在千万 QPS 量级,二元状态会带来一个突出的问题,状态切换的冲击过大。
千万 QPS 分摊在数百台节点上,每台节点承担数万 QPS。如果某一刻有 10% 的节点因为某个指标波动被同时判定为不健康并摘除,剩余节点需要瞬间多承接约 11% 的流量。在本就高负载的千万 QPS 场景下,这种突发的流量再分配很容易导致剩余节点过载,进而触发更多节点被摘除,形成级联故障。
多级健康状态通过引入中间态来缓解这个问题。

多级状态的核心价值是提供了渐进式的流量调整能力。从 Healthy 到 Degraded 不是断崖式地摘除,而是逐步降低权重,给系统留出缓冲。这种缓冲在千万 QPS 量级尤为重要,它既避免了带病上岗,也避免了一刀切摘除所引发的连锁反应。
核心矛盾:检查越深,误摘越广
回到文章开头的故障场景。深度健康检查引入了依赖检查,意味着一旦共享依赖出现故障,所有依赖它的节点都可能同时报告不健康。
在百万 QPS 量级,这个问题或许不致命,节点数量有限,运维团队有时间介入处理。但在千万 QPS 量级,节点数百上千,几秒内全部被摘除的后果远比依赖故障本身严重得多。
有损服务优于无服务,这是解决这一矛盾的核心原则。
围绕这个原则,架构上需要考虑以下几个关键设计。
5.1 摘除比例上限
无论健康检查结果如何,负载均衡器在任何时刻摘除的节点比例都不应超过一个安全阈值(例如不超过总节点数的 30%~50%)。当异常节点比例超过阈值时,系统应判定这更可能是检测体系或共享依赖的问题,而非所有节点都真的坏了,此时应保留节点继续提供有损服务,同时触发告警由人工介入。

5.2 依赖检查与摘除逻辑的解耦
另一种思路是将依赖异常与节点摘除解耦,依赖检查的结果不直接驱动节点摘除,而是驱动流量的降级策略。
例如,当检测到缓存依赖不可用时,不是将节点标记为不健康并摘除,而是将节点标记为缓存不可用状态,负载均衡器据此将该节点的流量路由到可以容忍高延迟的降级通道。这样,节点虽然服务质量下降了,但依然在线、依然在消化流量,不会出现全量摘除导致的服务中断。
5.3 健康检查与熔断器的协作
依赖检查和熔断器在依赖异常这个场景上存在职责重叠,两者都在试图处理依赖不可用的问题,但处理维度不同。
健康检查的职责在负载均衡层面,决定的是流量要不要发给这个节点。而熔断器的职责在服务调用层面,决定的是这个节点要不要继续调用某个依赖。

理想的协作模式是:熔断器负责在服务内部快速隔离故障依赖、执行降级逻辑;健康检查则将熔断器的状态作为输入之一,如果一个节点的核心依赖已经被熔断,这个信息可以反馈到健康检查的判定中,但最终的摘除决策仍应综合多维度信息来做,而不是简单地依赖被熔断了就摘除节点。
架构设计的几个关键权衡
6.1 主动探测 vs. 被动观测
深度健康检查的数据来源有两种路径。

- 主动探测可以检查真实流量覆盖不到的维度(如依赖连通性、资源余量),且不依赖持续流量,对新上线节点或低流量节点也能判定。劣势是探测结果与真实流量表现之间可能存在偏差,且探测本身有开销。
- 被动观测基于真实流量的成功率、延迟来判定,反映的就是真实服务能力,且零额外开销。劣势是需要持续流量才能产生数据,对于流量极低或刚上线的节点无法提供有效判定。
在千万 QPS 系统中,通常的做法是 主动探测保底、被动观测驱动精细调度,用主动探测确保基础的可用性判定,用被动观测的实时数据来驱动权重的动态调整。
6.2 检查频率与探测开销
健康检查频率需要在故障发现速度和探测开销之间取得平衡。
在百万 QPS 量级,5~10 秒的检查间隔是常见选择。到了千万 QPS 量级,可以简单算一笔账:如果单节点承担 3 万 QPS,5 秒的检测盲区意味着该节点故障后可能有约 15 万个请求被发送到故障节点。这是否可接受,取决于业务的容忍度。
但提高频率并非没有代价。当集群有 500 个节点时,每秒一次的主动探测就意味着探测系统每秒需要发出 500 次检查请求。如果每次检查涉及依赖探测,这些请求还会进一步扇出到各依赖组件。
一个常见的优化策略是 自适应频率:节点状态稳定时使用较低的检查频率;一旦检测到状态变化(如从 Healthy 变为 Degraded),立即提高检查频率以加速确认。同时,依赖检查尽量采用轻量化方式,基于连接池状态或最近一次真实请求的结果来推断,而非每次都发起独立的探测请求。
6.3 抖动容忍:用确定性换速度
在大规模集群中,网络抖动、瞬时负载尖峰等因素可能导致单次健康检查失败。如果一次超时就立即改变节点状态,在千万 QPS 规模下可能引发频繁的状态翻转,一个节点反复在健康和不健康之间跳动,每次状态切换都会触发流量重新分配,这种震荡本身就是一种系统不稳定因素。
常见的抗抖动策略包括:要求连续多次检查失败才判定状态变化、使用滑动窗口统计而非单次结果、以及从多个探测点交叉验证等。这些机制本质上都是 用一定的检测延迟换取判定的准确性,具体的权衡点取决于业务对故障感知速度和误判代价的敏感度。
总结
健康检查的演进,本质上是对节点可用性这一概念认知的不断深化。从活着到能响应再到服务质量达标,每一步跃迁都是规模增长倒逼出来的。
但深度健康检查并不是检查越多越好的线性堆叠。它引入了一个核心矛盾,检查维度越多,尤其是涉及共享依赖的检查,越容易在依赖故障时触发大面积节点摘除,造成比原始故障更严重的后果。因此,千万 QPS 量级的健康检查架构设计,不仅要回答怎么检查得更深,更要回答检查出问题后怎么处理才不会让事情变得更糟。
有损服务优于无服务,这或许是深度健康检查架构中最重要的一条设计原则。 每一次在云栈社区探讨这些架构细节,都是为了让大规模系统的运转更稳健、更平滑。