Nacos 服务发现与注册
Nacos 发现适配覆盖两条方向:客户端查询实例,以及应用启动后向 Nacos 注册自己。
先给答案:服务发现同时维护“我是谁”和“别人在哪里”两条链
Section titled “先给答案:服务发现同时维护“我是谁”和“别人在哪里”两条链”注册链负责实例启动、元数据上报、心跳和注销;查询链负责从本地缓存或 Nacos 获取实例列表,再交给负载均衡选择目标。两条链的故障语义不同:注册失败影响可见性,查询失败可能触发缓存降级。
本地缓存提高可用性,却可能返回过期实例;心跳和健康检查也不能保证业务一定可用。排查调用失败时要区分服务不存在、实例列表陈旧、实例已摘除但缓存未更新,以及真正的网络或业务错误。
查询: LoadBalancer -> DiscoveryClient -> NacosServiceDiscovery -> Naming注册: WebServerReady -> AutoServiceRegistration -> NacosServiceRegistry \-> ServiceCache fallbackNacosDiscoveryClient:36实现DiscoveryClient。getInstances:60-72成功时写入ServiceCache,失败时按 failure tolerance 返回缓存。- 服务列表查询位于
NacosDiscoveryClient:81-87,同样支持缓存降级。 ServiceCache:30-64保存 serviceId 和实例列表,是进程级缓存。- 响应式实现
NacosReactiveDiscoveryClient:59-77用 Flux 包装同一语义。 NacosLoadBalancerClientConfiguration:58-118将发现接到ServiceInstanceListSupplier。
NacosServiceRegistry:42实现ServiceRegistry<Registration>。register:61-95把NacosRegistration转成 NamingService 注册请求。deregister:97-119在停机或注销时移除实例。NacosAutoServiceRegistration:72-80接入 Cloud 注册生命周期。NacosServiceRegistry:147-150支持配置变化后的注销再注册。
为什么保留缓存降级
Section titled “为什么保留缓存降级”替代方案:每次发现都强依赖 Nacos,异常直接向上抛出。
为什么不行:注册中心故障会把已有实例视为全部不可用,造成二次故障。
证据:NacosDiscoveryClient#getInstances:60-72 在 failure tolerance 打开时返回 ServiceCache。
| 场景 | 现象 | 原因 | 规避 |
|---|---|---|---|
| 缓存过期实例 | 请求打到已下线节点 | 容错缓存牺牲新鲜度 | 配合超时、健康检查和故障窗口 |
| 注册端口错误 | 实例存在但请求失败 | 管理端口与业务端口混淆 | 检查 NacosRegistration 最终端口 |
| 固定 URL | 不触发发现 | LoadBalancer 只处理服务名 | 不同时配置固定 URL 和服务名路由 |
服务发现缓存是“过期可用”策略的实例,适合拓扑等读多写少数据,但必须明确最大陈旧时间。
面试锚点
DiscoveryClient和ServiceRegistry分别解决什么问题?- Nacos 发现失败时为什么可以返回缓存?
- 注册发生在 WebServerReady 前还是后?