Intro
Nacos作为服务注册中心,支持两种实例类型
- 临时实例 Ephemeral (默认)
- 持久化实例 Persistent
心跳机制有什么用呢?它主要用于临时实例的健康检查,确保注册中心能及时感知到实例的存活状态
1 临时实例的心跳机制
client主动上报心跳+server健康检查
1.1 client
客户端实例注册后,会启动一个定时任务,每隔固定时间间隔,就会向Nacos server发送Beat,就是心跳包。默认心跳间隔一般是5s,可以自定义。
心跳的内容就是实例信息,IP,port,权重,元数据等。
- 在Nacos 1.x版本,是通过HTTP PUT请求 /nacos/v1/ns/instance/beat发送。容易产生大量请求。
- Nacos 2.x版本则切换为gRPC长链接,利用连接本身的保活机制+服务端主动去检测。
sequenceDiagram
participant Client
participant Server
Client->>Server: 注册实例 (gRPC 连接)
loop 每隔一段时间
Client->>Server: 连接保活 (keepalive)
end
Note over Server: 定时检查无数据连接 >20s → 剔除
1.2 server
服务端接收到心跳后,更新实例的最后心跳时间 lastBeat。服务端也启动了一个定时任务,每5s检查一次,超过15s未收到心跳,标记该实例为不健康。
healthy = false
超过30s没收到,直接从服务列表中删除。这保证实例异常下限可以被快速感知到。
Nacos2.x
// ConnectionManager.start()
executor.scheduleWithFixedDelay(() -> checkConnections(), 3, 3, TimeUnit.SECONDS);
private void checkConnections() {
for (Connection conn : connections) {
if (System.currentTimeMillis() - conn.getLastActiveTime() > 20_000) {
// 标记过期,探活失败则 unregister instances
}
}
}
2持久化实例的健康检查
持久化实例不依赖client的心跳,而是服务端主动检测,有三种检测模式:TCP,HTTP,或者MySQL,TCP是默认方式。异常时仅标记为不健康,不会剔除实例,比较适合DNS场景。
3 配置心跳超时时间
想自定义快速上下线,觉得默认的30s剔除太慢,我们就可以通过实例的metadata配置来缩短这个时间。
spring:
cloud:
nacos:
discovery:
metadata:
preserved.heart.beat.interval: 5000 # 心跳间隔(毫秒,默认 5000)
preserved.heart.beat.timeout: 15000 # 心跳超时(毫秒,默认 15000)标记不健康
preserved.ip.delete.timeout: 30000 # 实例删除超时(毫秒,默认 30000) 剔除实例
最后:为什么需要心跳机制
心跳是Nacos实现高可用的核心机制。正常下线的话,客户端会主动发送注销请求。如果客户端异常下线,比如进程崩溃,服务端收不到心跳,就会自动标记,剔除,避免调用不可用的实例。
Nacos的心跳设计是借鉴了Eureka的,它比Eureka更灵活,支持AP/CP的切换。如果生产环境需要更快的响应,我们也可以自定义metadata配置。