健康检查类型:主动检查 vs 被动检查

健康检查的方式,说白了就两大类:主动去问,或者被动地等信号。我刚开始做密码接口系统时,总觉得只要用一种就够了,后来线上出过一次事故才明白——两者必须搭配使用,缺一不可。

主动检查(Proactive Health Check)

主动检查的意思是:系统按固定周期,主动向目标接口发送探测请求,看它能不能正常响应。

举个例子。我维护过一个加解密网关,每30秒对后端SM4服务发一次“ping”请求。如果连续3次没收到200响应,我就把该节点从负载池里摘掉。

  • 原理:定时任务 / 调度器发探针(HTTP、TCP、自定义协议)
  • 优势:可以提前发现问题,不等用户报错
  • 劣势:额外网络开销,可能误杀正常节点(比如一次丢包)

常见实现

# 伪代码示例:主动健康检查轮询
def active_health_check(node_url, interval=30):
    while True:
        try:
            resp = requests.get(node_url + "/health", timeout=2)
            if resp.status_code != 200:
                mark_unhealthy(node_url)
        except Exception:
            mark_unhealthy(node_url)
        time.sleep(interval)

这里要注意超时设置。我见过有人设成5秒,结果因为网络抖动,明明服务正常却被踢了。我个人习惯设1~2秒,配合重试机制。

被动检查(Reactive Health Check)

被动检查正好反过来——我不主动问,而是在正常业务请求中去“听”对方的错误信号。

你想想看,如果一个节点每100次请求就出错20次,那它肯定有问题。被动检查就是靠统计错误率、响应时间、连接失败次数来判断的。

  • 原理:拦截业务请求的返回状态,累计错误计数或延迟指标
  • 优势:零额外开销,真实反映业务视角的健康度
  • 劣势:问题已暴露给用户,不能提前预警

常见实现

# 伪代码:被动错误计数熔断
error_count = 0
threshold = 5

def on_request_failure():
    global error_count
    error_count += 1
    if error_count >= threshold:
        circuit_breaker_open()

def on_request_success():
    global error_count
    error_count = 0

我曾经在密码机集群上只用被动检查,结果某一台节点悄悄返回了「密钥被锁定」的错误,因为业务没报错(只是重试了),直到用户反馈解密失败才意识到。这就是被动检查的盲区——很多时候错误被上层吞掉了,你根本听不到。

主动 vs 被动:关键差异

维度 主动检查 被动检查
触发方式 定时轮询 业务请求事件
发现时机 故障前/刚发生时 问题已暴露后
资源消耗 额外请求开销 几乎为零
误判风险 可能误杀(网络抖动) 可能漏判(错误被静默)
适用场景 对延迟不敏感、节点数少 高并发、对额外流量敏感

实际上,我建议你两者都用。主动检查负责“巡逻”,被动检查负责“补漏”。

两者协同的典型流程

主动检查流程 定时发送探测请求 等待响应(超时 N 秒) 成功? → 继续保持 失败/超时 → 摘除节点 被动检查流程 业务请求正常转发 拦截返回状态码 成功率 > 阈值? 失败率超标 → 熔断 故障转移决策 更新路由表 / 通知管理者

最佳实践:用主动检查做快速探测(比如每10秒一次),用被动检查做深度防御(比如滑动窗口统计错误率)。只有主动发现问题时,先尝试重试还是直接降级?我建议看业务容忍度——密码接口通常不允许重试导致重复加密,所以我会直接切换备用节点。

实际项目中的避坑指南

  1. 别让主动检查变成 DDoS。我有一次把探测间隔设成1秒,上百个节点一起打探针,结果把监控服务打挂了。现在我会加一个 jitter 随机偏移,避免雪崩。
  2. 被动检查的阈值要动态调整。比如凌晨业务量低,错误率稍微高一点可能只是正常波动。我后来按时间段分了不同的熔断阈值。
  3. 两种检查的结果要合并。如果一个节点主动检查失败,但被动检查显示业务流量成功,那大概率是探针本身的问题。我曾经遇到过探针路径和业务路径不同,导致误判——所以探针要和业务请求走同一条链路。

小技巧:在密码接口场景下,除了看 HTTP 状态码,还要检查响应体里的「密钥状态」字段。比如主动检查发一个“测试解密”请求,验证返回的明文是否正确。这样能发现更隐蔽的故障。

注意:被动检查依赖业务流量,如果高峰期某节点被限流或流量降级,它的失败率可能是0,但实际上已经不可用。所以一定要搭配主动检查的“空载探测”。

嗯,这两种检查方式说起来简单,但组合起来能玩的细节很多。我个人习惯在项目初期先用“主动为主、被动为辅”的配置跑起来,等数据多了再调整比例。你想想看,如果一开始就搞复杂的滑动窗口,运维同学可能直接懵掉——先跑通,再优化,永远是王道。