Skip to content

Spring Cloud 如何实现服务注册? ​

  • 标签:Spring Cloud、微服务、后端

🏛 业务架构师 ​

Spring Cloud 的服务注册实现以 Nacos 为例(国内标准),三步讲清:

1. 客户端自动注册(启动期):

  • 引入 spring-cloud-starter-alibaba-nacos-discovery,应用启动时 NacosAutoServiceRegistration 执行;
  • 通过 Nacos 的 OpenAPI/gRPC 调用注册接口,把 服务名 + IP + 端口 + 集群 + 权重 + 元数据(版本/标签)注册上去;
  • 注册信息附带临时实例语义:靠心跳维持(默认 5 秒一跳),15 秒不健康、30 秒剔除——实例宕机自动摘除,扩容自动上线,弹性伸缩的注册面自动化。

2. 服务发现(消费侧):

  • 消费者启动拉取服务列表并本地缓存 + 订阅变更推送(Nacos 用 UDP/gRPC 推送变更,秒级感知);
  • Feign 调用时按服务名从本地列表选实例(LoadBalancer),注册中心挂了靠缓存仍可调用。

3. 健康检查双模式(Nacos 的产品差异点):

  • 临时实例:客户端心跳上报(默认,微服务场景);
  • 持久实例:服务端主动探测(DB、Redis 这类非 JVM"基础设施型服务"用)。

架构师视角的实践要点:

  • 元数据是流量治理的载体:实例带版本/灰度标签(version=gray),网关和 LB 按标签路由——注册中心的元数据设计直接决定灰度发布的能力;
  • 优雅上下线:下线前先反注册 + 网关摘流量,K8s 场景配 preStop,避免滚动发布打到正在关闭的实例;
  • 注册中心高可用(Nacos 三节点集群 + 客户端缓存兜底)是上线前检查单的必选项。

🏗 系统架构师 ​

以 Nacos 为例的注册链路:

  1. 自动装配:引入 spring-cloud-starter-alibaba-nacos-discovery,自动配置生效;
  2. 注册触发:服务启动后(WebServerInitializedEvent)NacosClient 上报 服务名:IP:端口:集群:权重:元数据;
  3. 临时实例(默认,AP 模式):客户端 5s 心跳;15s 未收到标记不健康(推送下线)、30s 未收到摘除——服务端不主动探测,靠心跳 TTL;
  4. 持久实例(CP 模式):Raft 强一致持久化,服务端主动健康检查——适合 db、redis 这类没有「客户端 SDK」的组件;
  5. 下线:正常停机 deregister 加优雅停机摘流量;宕机靠 30s 超时摘除。

架构细节:K8s 里注册的是 Pod IP(绕过 Service 的 kube-proxy,否则丢失真实来源,熔断与灰度元数据失效);消费方拿列表后本地缓存,2.x 走 gRPC 订阅推送。

治理要点:发布流程必须是「反注册 → 等待心跳/推送窗口 → 处理完存量请求 → 退出」,窗口没算对,滚动发布必有 5xx 尖刺。

💻 全栈开发专家 ​

以 Nacos 为例(接入 10 分钟的活):

xml
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
yaml
spring:
  application:
    name: order-service          # 服务名 = 注册的 key
  cloud:
    nacos:
      server-addr: nacos:8848
      discovery:
        namespace: prod
        group: BIZ
        metadata:                # 元数据:灰度/版本路由用
          version: v2

启动自动注册:NacosServiceRegistry#register() 监听 WebServerInitializedEvent(端口确定后触发),调 Nacos API 把 IP:port + 元数据注册为临时实例;之后每 5s 心跳,15s 未达标记不健康、30s 剔除。K8s 下注册 Pod IP,多网卡时用 spring.cloud.nacos.discovery.ip 指定——注册错 IP 是经典踩坑。

消费方:@FeignClient(name = "order-service"),调用时 LoadBalancer 从本地缓存的实例列表选一个。

优雅停机配套必做:K8s preStop 里先反注册(或 server.shutdown=graceful + 睡眠),等消费方缓存刷新再杀进程——否则滚动更新期间流量打到将死实例,发布时 502 尖刺的老根因就是它。