后端健康检查:系统自愈的 “体温计”

82 阅读4分钟

在分布式系统中,服务故障是常态 —— 数据库连接池耗尽、缓存集群不可用、磁盘空间满了,这些问题如果不能及时发现,可能引发连锁反应导致系统崩溃。健康检查机制就像系统的 “体温计”,实时监测各组件状态,为故障自愈和人工干预提供依据。

健康检查的核心价值

健康检查的核心是故障早发现,具体价值体现在:

  • 及时发现亚健康状态(如磁盘使用率 80%),提前预警
  • 为负载均衡器提供依据(剔除不健康实例,避免请求分发到故障节点)
  • 辅助排查问题(通过各组件的健康状态定位故障点)
  • 支持自动恢复(如配合 K8s 实现故障实例重启)

健康检查的三个层级

1. 基础存活检查(Liveness Probe)

检查服务进程是否存活,是最基础的健康指标。

  • 实现方式:HTTP 接口(如/actuator/health/liveness)、TCP 端口监听、进程 PID 检查

  • 触发动作:若失败,通常会重启服务实例(如 K8s 的 livenessProbe 失败会重启容器)

代码示例(Spring Boot Actuator)

# application.yml 配置基础健康检查
management:
  endpoint:
    health:
      probes:
        enabled: true # 启用存活和就绪探针
  endpoints:
    web:
      exposure:
        include: health # 暴露/actuator/health端点

2. 就绪检查(Readiness Probe)

检查服务是否已准备好接收请求(如初始化完成、依赖服务可用)。

  • 区别于存活检查:存活检查关注 “进程是否活着”,就绪检查关注 “能否正常工作”

  • 触发动作:若失败,负载均衡器会将实例从服务列表中移除,不再分发请求

实现逻辑

// 自定义就绪检查指示器(Spring Boot)
@Component
public class ReadinessIndicator implements HealthIndicator {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private DataSource dataSource;

    @Override
    public Health health() {
        // 检查Redis是否可用
        try {
            redisTemplate.opsForValue().get("health-check");
        } catch (Exception e) {
            return Health.down().withDetail("redis", "不可用").build();
        }
        // 检查数据库连接
        try (Connection conn = dataSource.getConnection()) {
            if (!conn.isValid(1000)) {
                return Health.down().withDetail("db", "连接无效").build();
            }
        } catch (SQLException e) {
            return Health.down().withDetail("db", "连接失败").build();
        }
        // 所有依赖可用,返回健康状态
        return Health.up().build();
    }
}

3. 深入健康检查(Detailed Health)

检查核心业务链路的健康状态(如 “下单流程能否正常执行”),通常包含:

  • 依赖服务健康度(数据库、缓存、消息队列的连接数、响应时间)

  • 系统资源状态(CPU 使用率、内存占用、磁盘空间、JVMGC 情况)

  • 业务指标(如订单成功率、支付接口响应时间)

实现方式

  • 集成 Prometheus + Grafana:监控系统资源和业务指标
  • 自定义健康接口:如/api/health/detailed,返回各组件的详细状态

健康检查的实战策略

1. 分级告警

根据健康状态严重程度设置不同告警级别:

  • 警告(WARN):磁盘使用率 > 80%、缓存命中率 < 90%
  • 严重(ERROR):数据库连接失败、核心接口响应时间 > 3s
  • 紧急(FATAL):服务实例就绪检查失败、订单成功率 < 90%

2. 依赖隔离

健康检查应避免 “依赖服务故障导致自身健康检查失败” 的级联问题:

  • 非核心依赖(如日志服务)故障,不应影响主服务的就绪状态
  • 对依赖服务的检查设置超时时间(如 1 秒),避免阻塞自身健康检查

3. 性能控制

健康检查本身不应成为系统负担:

  • 检查频率合理(如基础检查 10 秒一次,详细检查 1 分钟一次)
  • 避免在健康检查中执行耗时操作(如全表扫描、大量计算)

避坑指南

  • 不要过度依赖单一指标:如只检查 HTTP 端口存活,不检查数据库连接,可能导致 “服务活着但不能用”

  • 健康检查接口自身要可靠:避免健康检查接口依赖复杂逻辑(如自身也连接数据库),否则可能 “误判死亡”

  • 结合业务场景设计:支付服务重点检查与支付网关的连接,缓存服务重点检查内存和命中率

健康检查不是 “摆设”,而是分布式系统稳定性的第一道防线 —— 一个设计良好的健康检查机制,能在故障发生的第一时间发出预警,甚至通过自动恢复避免服务中断,这是后端系统 “韧性” 的重要体现。