什么是服务注册与发现?为什么微服务需要注册中心?
简化版
服务注册与发现是微服务之间找到彼此的机制。服务提供者启动后把自己的地址、端口、实例信息注册到注册中心;服务消费者调用时从注册中心获取可用实例列表,再通过负载均衡选择一个实例发起请求。
微服务实例数量多、地址会动态变化,不能靠写死 IP。注册中心解决的是服务地址动态管理、实例上下线感知、健康状态维护和调用方自动发现的问题。
详细版
在单体或小规模系统中,服务地址可能固定写在配置里。但微服务系统通常会有很多服务和实例,实例会因为扩缩容、发布、故障、容器调度而频繁变化。如果调用方仍然写死地址,就会出现发布困难、故障感知慢、扩容不生效等问题。
注册中心提供一个服务目录。服务提供者启动时注册,定期发送心跳或续约;注册中心维护实例列表和健康状态;消费者订阅或拉取服务列表,并在本地缓存;调用时结合负载均衡、健康检查和容错策略选择实例。
面试中要强调:注册中心不是业务请求的转发代理,调用方通常不会把每次业务请求都打到注册中心。注册中心主要在控制面提供服务地址和状态,真正的数据面调用通常是消费者直接访问服务提供者。
完整版教学
一、先理解服务地址为什么不能写死
微服务系统的实例是动态的。一个订单服务今天可能有 5 个实例,晚上大促扩容到 30 个实例,发布时又会滚动替换一批实例。容器平台调度后,实例 IP 和端口也可能变化。
如果调用方把地址写死,就会遇到这些问题:
- 扩容后调用方不知道新实例,新增容量用不上。
- 实例故障后调用方继续请求坏地址,错误率升高。
- 发布时地址变化,需要同步修改多个调用方配置。
- 多环境、多机房下地址管理混乱。
- 服务拆分越多,维护成本越高。
注册中心的价值就是把“服务在哪里”从代码和配置里抽出来,变成动态可维护的服务目录。
二、服务注册与发现的基本角色
服务注册与发现一般有三个角色:
- 服务提供者:对外提供接口的服务实例,比如订单服务实例。
- 服务消费者:需要调用其他服务的服务,比如支付服务调用订单服务。
- 注册中心:保存服务名到实例地址列表的映射。
典型流程是:
服务提供者启动
↓
向注册中心注册实例信息
↓
服务消费者订阅服务实例列表
↓
消费者本地缓存列表
↓
调用时选择一个健康实例
这里的“服务名”很关键。调用方通常不关心具体 IP,而是调用逻辑服务名,比如 order-service。注册中心负责把逻辑服务名解析成当前可用实例列表。
三、注册中心保存哪些信息
注册中心不只保存 IP 和端口,还可能保存很多元数据:
- 服务名和实例 ID。
- IP、端口、协议,比如 HTTP、gRPC、Dubbo。
- 健康状态,比如 UP、DOWN、OUT_OF_SERVICE。
- 权重,用于负载均衡。
- 版本号,用于灰度发布或兼容路由。
- 机房、可用区、集群、环境标签。
- 实例启动时间、心跳时间和临时实例标识。
这些元数据让服务发现不仅能“找到地址”,还能支持就近访问、灰度路由、权重流量、故障隔离等治理能力。
四、服务发现有拉取和订阅两种思路
消费者获取服务列表通常有两类方式。
第一类是主动拉取。消费者定期向注册中心查询某个服务的实例列表,并更新本地缓存。这种方式简单,但变更感知有延迟。
第二类是订阅通知。消费者订阅某个服务,注册中心在实例变化时通知消费者更新本地缓存。它实时性更好,但连接和通知机制更复杂。
实际系统常常结合两者:订阅用于及时感知变化,定期全量拉取或校验用于兜底,避免通知丢失导致本地缓存长期不准。
五、注册中心不在每次业务请求链路上
这是面试中的高频易错点。注册中心通常不转发业务流量。消费者会先从注册中心获取实例列表,缓存在本地,然后直接调用提供者。
错误理解:消费者 → 注册中心 → 提供者
常见实际:消费者 → 提供者
↑
本地服务列表来自注册中心
如果每次业务请求都经过注册中心,注册中心会变成性能瓶颈和单点风险。正确设计是注册中心负责控制面,服务调用走数据面直连。
六、注册中心和 DNS 的区别
DNS 也能把名字解析成地址,但注册中心比普通 DNS 更贴近服务治理。
注册中心通常支持更快的实例上下线感知、健康状态、元数据、订阅通知、权重、版本、集群标签等能力。DNS 更通用,但缓存时间、健康检查和元数据表达能力通常不如专门注册中心灵活。
有些系统会结合两者:外部入口或跨语言基础发现用 DNS,内部微服务治理用注册中心。
七、面试回答建议
回答这道题可以按四步:
- 定义:服务提供者注册,消费者发现可用实例。
- 背景:微服务实例动态变化,不能写死 IP。
- 流程:注册、心跳、拉取/订阅、本地缓存、负载均衡调用。
- 边界:注册中心不转发业务请求,故障时客户端要有缓存兜底。
如果能补充服务元数据和健康检查,答案会更像工程实践,而不是只背概念。
八、常见追问和落地边界
面试官经常会追问注册中心挂了怎么办。这里要明确说:消费者本地缓存已有实例列表,因此存量调用可以继续;但新实例注册、故障实例摘除和元数据变更会受影响。这个回答能体现你知道注册中心处在控制面,而不是每次调用的数据面。
另一个追问是注册中心和负载均衡的关系。注册中心提供候选实例列表,负载均衡负责从列表里选一个实例。服务发现解决“有哪些实例”,负载均衡解决“这次调哪一个”。两者经常一起出现,但不是同一件事。
九、常见误区与追问
这道题要紧扣「服务发现」本身回答,不能把它混成泛泛的服务注册与发现套话。面试官通常会沿着“为什么需要、流程怎么走、失败怎么兜、代价是什么”继续追问,所以回答要覆盖注册、心跳、健康检查、实例缓存、路由选择和注册中心故障兜底。
| 回答层次 | 要讲清的内容 | 容易漏掉的边界 |
|---|---|---|
| 核心结论 | 服务发现让消费者通过服务名找到可用实例,解决实例动态上下线和地址变化问题 | 不要停在名词解释 |
| 流程机制 | 提供者注册实例 -> 注册中心保存列表 -> 消费者订阅服务名 -> 本地负载均衡选择实例 -> 心跳更新健康状态 -> 异常时缓存和重试兜底 | 要说清触发点、状态变化、确认点和失败兜底 |
| 工程取舍 | 10 个订单服务实例扩到 20 个时,调用方不应手工改 IP,而应从注册中心自动拿到新列表 | 服务发现降低地址治理成本,但会引入缓存陈旧、摘除延迟、注册中心可用性和客户端行为一致性问题 |
服务发现 面试拆解:
1. 提供者注册实例
2. 注册中心保存列表
3. 消费者订阅服务名
4. 本地负载均衡选择实例
5. 心跳更新健康状态
6. 异常时缓存和重试兜底
记忆钩子:先给结论,再拆流程,再讲数字例子和失败边界;回答「服务发现」时要围绕题目问法收束,不要把相邻概念堆成一段没有重点的名词清单。
- 误区:服务发现就是 DNS。 DNS 能解析名字,但微服务还需要健康状态、权重、元数据和快速摘除。
- 误区:注册中心只在启动时用一次。 实例会扩缩容和故障,消费者要持续感知变化。
- 误区:服务发现能保证调用一定成功。 它只提供实例选择,调用仍需超时、重试、熔断和降级。
- 追问:服务发现解决什么问题? 解决动态实例地址管理和调用方自动找到可用提供者。
- 追问:它和负载均衡什么关系? 服务发现提供候选实例,负载均衡决定本次调用哪一个。
- 追问:注册中心挂了怎么办? 客户端用本地缓存继续调用,后台重连并刷新。
十、加强记忆
服务注册与发现可以记成“微服务通讯录”。服务提供者把自己登记进去,消费者查通讯录找到可用实例,然后直接打电话过去。
注册中心管的是地址和状态,真正的业务调用通常由消费者直接访问服务实例。