服务发现
解释服务实例地址动态变化时,客户端或网关如何通过注册表、DNS 或平台控制面找到健康实例并完成请求路由。
#concept
#growing
#backend
#architecture
[!info] related notes
- 所属 MOC:Distributed Systems MOC
- 前置:计算机网络 MOC、分布式系统
- 实现:etcd、Apache ZooKeeper
- 入口治理:API Gateway、Nginx MOC
服务发现
[!abstract] 一句话定义 服务发现把稳定的逻辑服务名解析为当前可用实例集合,并持续处理实例注册、健康状态、变更通知、负载均衡和失效端点,使调用方不必把动态 IP/端口写死。
为什么不能写死地址
容器和云环境中实例会:
- 自动扩缩;
- 重启并更换 IP;
- 滚动发布;
- 跨 Zone 迁移;
- 因健康检查失败被摘除。
静态地址无法及时反映这些变化。
基本模型
Service Instance
→ register / advertise endpoint + metadata
→ Registry / DNS / Control Plane
→ Client / Proxy discovers endpoint set
→ Load Balance
→ invoke instance
控制面维护“有哪些实例”;数据面负责把真实请求发给某个实例。
两种发现模式
Client-side Discovery
Client → Registry
Client selects instance
Client → Instance
优点:少一跳、可定制负载策略。代价:每种语言客户端都要实现发现、缓存、重试和负载均衡。
Server-side Discovery
Client → Load Balancer / Gateway / Service Mesh
Proxy discovers and selects instance
优点:客户端简单、策略集中。代价:增加 Proxy / Control Plane 复杂度和一跳。
DNS 也是服务发现
DNS A / AAAA / SRV 和集群内 DNS 可以把服务名解析到一个或多个地址。
优点:标准、通用。边界:
- TTL / Client Cache 可能保留旧地址;
- DNS 不直接表达复杂权重、负载和完整健康状态;
- 不同 Runtime 的 DNS Cache 行为不同;
- 连接池可能在 DNS 更新后仍复用旧连接。
Registry 里应保存什么
常见元数据:
- Service Name / Instance ID;
- IP / Port / Protocol;
- Zone / Region;
- Version / Deployment;
- Weight / Capability;
- Health / Readiness;
- Lease / Last Heartbeat;
- TLS / Identity Metadata。
不要把大量业务配置和秘密无边界地塞进 Registry。
Registration 与 Health
Self-registration
实例启动后主动注册并续租。简单直接,但实例需要 Registry Client 和正确注销/失效逻辑。
Third-party Registration
平台、Sidecar 或 Controller 根据实际运行状态注册。应用更简单,控制面更统一。
健康不只等于进程存活:
Liveness → 是否需要重启
Readiness → 是否应接新流量
Capability / Version → 是否适合当前请求
Stale Endpoint
发现数据必然有传播和缓存延迟。调用方应接受:
endpoint returned by registry
→ instance may fail before request arrives
因此仍需要 Connect Timeout、Retry(安全时)、Load Balancer Ejection 和幂等。Service Discovery 不能替代调用时故障处理。
Watch / Push 与 Poll
- Poll:实现简单,但更新慢且增加 Registry 读负载;
- Long Poll / Watch:变化更快,但要处理断线、版本缺口和重建;
- Local Cache:降低控制面依赖,但必须有 TTL / Revision 和失效策略。
正确模式通常是 Initial List + Revision / Version + Watch,断线或 Compaction 后重新全量同步。
启动和关闭
startup:
initialize dependencies
→ become ready
→ register / advertise
shutdown:
mark not ready / deregister
→ drain traffic
→ finish in-flight work
→ exit
先注册后初始化会让请求打到尚未可用实例;直接退出而不 Drain 会造成连接错误和重试风暴。
观测重点
registered / healthy instance count
registration and lease renewal failures
endpoint update latency
stale endpoint / connection failure rate
load distribution per instance / zone
registry availability and watch lag
drain and deregistration duration
设计检查表
- 逻辑服务名与实际 Endpoint 解耦。
- Client-side / Server-side Discovery 选择明确。
- Readiness 决定是否接流量,而不只看 Liveness。
- Registry 缓存、TTL、Revision 与断线恢复明确。
- 调用方仍有 Timeout、Retry 和失败摘除。
- 发布和关闭包含注册、摘流与 Drain 顺序。
- Zone / Version / Capability Routing 有可观测依据。