Nacos 健康检查是如何实现的?支持哪些健康检查协议?

在这里插入图片描述
Nacos 的健康检查是确保服务注册中心中只包含存活且能够正常处理请求的服务实例的关键机制。它能自动识别并(暂时或永久)移除故障实例,防止服务消费者将请求发送到无法响应的实例上,从而提高系统的整体可用性和稳定性。

Nacos 的健康检查实现方式主要取决于实例的类型(临时实例 vs 持久化实例)以及用户的配置

核心健康检查机制:

Nacos 主要通过以下两种方式来实现健康检查:

  1. 客户端心跳 (Client Beat) - 主要针对临时实例 (ephemeral=true)

    • 机制: 这是 Nacos 默认且最常用的健康检查方式,专门为临时实例设计。当一个服务实例(客户端)注册为临时实例时,Nacos Client SDK 会启动一个后台心跳线程 (BeatReactor)。
    • 过程:
      • 该线程会定期(默认 5 秒,可通过 spring.cloud.nacos.discovery.heart-beat-interval 或 SDK 参数配置)向 Nacos Server 发送一个心跳包(通常是一个轻量级的 HTTP PUT 或 UDP 请求,发送到 /nacos/v1/ns/instance/beat 接口)。
      • 这个心跳包本质上是在告诉 Nacos Server:“我还活着!”。
      • Nacos Server 接收到心跳后,会更新该实例的最后心跳时间戳 (lastBeatTimestamp)。
    • 服务端检查: Nacos Server 内部有一个定时任务 (ClientBeatCheckTask) 会定期扫描所有临时实例。
      • 如果一个实例的 当前时间 - lastBeatTimestamp 超过了一个超时阈值(默认 15 秒,preserved.heart.beat.timeout 元数据可配,或根据 interval 推算),Nacos Server 会将该实例标记为不健康 (healthy=false),但暂时不会移除。
      • 如果超过了另一个更长的剔除阈值(默认 30 秒,preserved.ip.delete.timeout 元数据可配,或根据 interval 推算),Nacos Server 会认为该实例已经彻底失联,并将其从服务列表中移除
    • 优点:
      • 轻量级: 对客户端和服务端压力较小。
      • 去中心化: 健康状态的维持责任主要在客户端。
      • 快速响应: 客户端宕机后,心跳停止,能在较短时间内被服务端检测到。
    • 缺点: 依赖客户端主动发送心跳,如果客户端进程卡死但未退出,可能无法及时停止心跳。
  2. 服务端主动探测 (Server Side Active Check) - 主要针对持久化实例 (ephemeral=false) 或可配置用于临时实例

    • 机制: 对于持久化实例,或者用户显式配置了健康检查类型时,Nacos Server 会扮演主动角色,定期向服务实例配置的检查端点发起探测请求,根据响应来判断实例的健康状态。
    • 过程:
      • Nacos Server 根据实例注册时提供的健康检查配置(通常在元数据 metadata 中指定),定期向实例的 IP:端口/检查路径 发起探测。
      • Nacos Server 分析探测请求的响应结果(如 TCP 连接是否成功、HTTP 状态码是否符合预期、数据库查询是否成功等)。
      • 根据探测结果更新实例的健康状态 (healthy 标志)。
    • 优点:
      • 服务端控制: 健康检查逻辑由服务端统一管理。
      • 更全面: 可以模拟真实的调用场景(如检查 HTTP 接口)。
      • 不依赖客户端心跳: 即使客户端心跳模块故障,只要服务本身能响应探测,就仍被认为是健康的。
    • 缺点:
      • 增加服务端负担: Nacos Server 需要消耗资源去探测所有配置了此模式的实例。
      • 配置相对复杂: 需要为实例配置正确的检查类型、端口、路径等。

支持的健康检查协议 (主要用于服务端主动探测):

当配置服务端主动探测时,Nacos 支持以下几种常见的协议/方式:

  1. TCP 端口探测:

    • 协议: TCP
    • 工作方式: Nacos Server 尝试与实例的 IP:检查端口 建立一个 TCP 连接。
    • 健康判断: 如果 TCP 连接能够成功建立(收到 SYN-ACK),则认为实例在该端口上是存活的,判定为健康。如果连接被拒绝 (RST) 或超时,则判定为不健康。
    • 配置 (metadata): 通常指定检查类型和端口。端口可以默认使用实例注册的端口,也可以通过元数据指定特定的检查端口。
      // 示例元数据
      {
              
              
        "preserved.heart.beat.interval": "5000", // 可选,影响心跳间隔
        "preserved.heart.beat.timeout": "15000", // 可选,影响不健康阈值
        "preserved.ip.delete.timeout": "30000", // 可选,影响剔除阈值
        "checkType": "TCP", // 指定检查类型
        "checkPort": "8081" // 可选,指定检查端口,默认是实例端口
      }
      
  2. HTTP 接口探测:

    • 协议: HTTP/HTTPS
    • 工作方式: Nacos Server 向实例的 http(s)://IP:检查端口/检查路径 发送一个 HTTP 请求(GET 或 POST)。
    • 健康判断: 通常根据返回的 HTTP 状态码来判断。如果状态码是 2xx(例如 200 OK),则认为健康。其他状态码(如 4xx, 5xx)或请求超时、连接失败则认为不健康。可以配置期望的状态码。
    • 配置 (metadata): 需要指定检查类型、检查路径,可选配置检查端口、请求方法、期望的状态码、自定义请求头等。
      // 示例元数据 - 检查 /actuator/health 端点
      {
              
              
        "checkType": "HTTP",
        "checkPath": "/actuator/health", // Spring Boot Actuator 健康端点
        "checkPort": "8080", // 可选,默认实例端口
        "checkMethod": "GET", // 可选,默认 GET
        "expectedResponseCode": "200" // 可选,默认检查 2xx
        // "headers": "X-Custom-Header:Value" // 可选,自定义请求头
      }
      
  3. MySQL 连接探测:

    • 协议: MySQL
    • 工作方式: Nacos Server 尝试使用提供的用户名和密码连接到实例对应的 MySQL 数据库,并执行一个简单的测试 SQL 语句(例如 SELECT 1)。
    • 健康判断: 如果连接成功并且测试 SQL 语句执行成功,则认为健康。如果连接失败、认证失败或 SQL 执行出错,则认为不健康。
    • 配置 (metadata): 需要指定检查类型、MySQL 用户名、密码,可选配置测试 SQL 语句。
      // 示例元数据
      {
              
              
        "checkType": "MYSQL",
        "user": "nacos_check_user",
        "pwd": "your_password",
        "cmd": "SELECT 1" // 可选,默认执行简单查询
      }
      
  4. 客户端上报 (Client Beat) - 再次强调:

    • 虽然不是服务端“主动”探测协议,但这是 Nacos 最基础、最常用的健康检查机制,适用于所有临时实例。它不涉及上述 TCP/HTTP/MySQL 协议的主动探测,而是依赖客户端周期性地发送“我还活着”的信号。

如何选择和配置:

  • 对于绝大多数动态伸缩的微服务(临时实例 ephemeral=true): 默认的客户端心跳机制通常是最佳选择,因为它轻量、高效且能快速响应实例下线。一般无需额外配置健康检查协议。可以通过调整心跳间隔和超时相关的元数据(preserved.*)来微调灵敏度。
  • 对于状态相对固定、需要服务端强管控健康状态的服务(持久化实例 ephemeral=false): 或者需要在临时实例上实现更复杂的健康检查逻辑(例如检查业务接口而非仅存活),可以选择服务端主动探测 (TCP, HTTP, MySQL)。配置方式主要是通过实例注册时的 metadata 来指定 checkType 及相关参数。
  • 全局配置 (不常用): 也可以通过 Nacos Server 的配置文件 (application.properties) 中的 nacos.naming.health-checker 相关属性设置全局默认的服务端检查类型,但这通常不如基于元数据的实例级配置灵活。

总结:

Nacos 提供了灵活的健康检查机制:

  1. 客户端心跳 (默认,用于临时实例): 客户端主动汇报存活状态。
  2. 服务端主动探测 (需配置,用于持久化或特定场景): 服务端按配置的协议 (TCP, HTTP, MySQL) 去检查实例。