订阅、推送与运维
服务消费者可以查询服务,也可以订阅服务变化。订阅适合长期运行的应用。Nacos 会在服务实例变化后推送新的发现视图,客户端再更新本地缓存并通知 listener。
查询和订阅
查询是一次性读取。订阅会在客户端连接下记录 subscriber,并返回当前 ServiceInfo 视图。后续服务变化时,服务端会向已订阅客户端推送新的视图。
| 动作 | 适用场景 |
|---|---|
| 查询服务实例 | 启动时读取下游地址,或不需要长期监听变化。 |
| 订阅服务变化 | 长期运行应用需要感知实例上下线、权重和健康变化。 |
| 取消订阅 | 当前应用不再需要某个服务的变化通知。 |
HTTP Client OpenAPI 适合查询指定服务实例,不提供长连接订阅能力。需要订阅时,优先使用官方 SDK。
推送和重试
Naming 推送携带订阅服务的当前发现视图。客户端收到推送后,会更新内存缓存和磁盘缓存,并根据实例 diff 通知 listener。
推送是当前连接生命周期内的尽力投递。推送失败时,服务端可以为目标 client 加入延迟重试。客户端也应能通过重新查询、重连 redo 和本地缓存恢复,从错过的推送中恢复。
本地缓存和 Failover
客户端通常会保存 service-info 缓存。它用于:
- 启动时加载最后已知服务视图。
- 网络中断时提供临时发现视图。
- 推送或查询结果变化时触发 listener。
Naming failover 是本地发现视图覆盖。当 failover switch 开启且某个服务有有效 failover data 时,SDK 可以返回 failover view,而不是服务端视图。
本地缓存和 failover 都不是服务端数据修复机制。不要用客户端本地数据反向修复注册中心。
重连和 Redo
连接断开后,客户端需要在重连后恢复运行时意图。Naming redo 覆盖:
- 临时实例注册。
- 批量临时实例注册。
- 服务订阅。
- 模糊订阅状态。
持久服务状态由服务端持有,除非某个操作明确属于运行时意图,否则不应由客户端 redo 恢复。
运维诊断
Naming 运维 API 和 Maintainer SDK 可用于检查或管理:
- Service 和 Instance 元数据。
- Cluster 健康检查配置。
- Client 列表和详情。
- 某个 client 发布或订阅的 service。
- 某个 service 的 publisher 和 subscriber。
- Naming 指标、开关和日志级别。
这些接口是管理接口面。它们可以帮助排查问题,但不应被普通业务应用作为运行时依赖。
常见问题
| 现象 | 排查方向 |
|---|---|
| 订阅没有收到变化 | 检查 SDK 连接、订阅 service 身份、listener 是否注册成功,以及服务端 subscriber 信息。 |
| 查询结果少于控制台实例列表 | 检查 cluster、enabled、healthy、保护阈值和客户端 selector。 |
| 实例下线后仍被客户端看到 | 检查客户端缓存、推送是否失败、是否处于 failover 模式。 |
| gRPC 客户端重连后实例没有恢复 | 检查 redo 数据、连接状态和注册请求错误。 |
| 服务列表或订阅者诊断慢 | 检查查询范围、分页大小、节点负载和可见性过滤。 |
生产建议
- 应用只订阅自己需要调用的服务,不要订阅全量服务。
- 关键服务观察 subscriber 数量、推送失败、连接数和健康实例比例。
- 使用
enabled=false做实例摘流时,确认调用方是否使用官方 SDK 或是否正确处理 enabled。 - failover 适合应急兜底,恢复后要及时退出 failover 模式。
- 管理工具访问大范围 Naming 数据时,应分页并控制频率。