服务注册与发现

微服务动态部署,IP 和端口随时变化,服务间调用需要通过注册中心查找目标地址。

核心问题

传统做法(写死 IP):
  serviceA.call("192.168.1.10:8080")
  → IP 变了就挂

服务注册与发现:
  serviceA.call("order-service")  // 逻辑名
  → 注册中心解析为当前可用的实例

K8s 原生发现(推荐)

K8s 通过 Service + CoreDNS 实现服务发现,无需额外注册中心。

Pod 启动 → 自动加入 Endpoint
Service 创建 → CoreDNS 注册 DNS 记录

调用方:
  http://order-service.prod.svc.cluster.local:8080
         ↑           ↑    ↑
       服务名    Namespace  固定后缀

K8s Service 类型:

类型用途
ClusterIP集群内部访问(默认)
NodePort暴露到节点端口,外部可访问
LoadBalancer云厂商提供外部 IP
Headless直接返回 Pod IP(StatefulSet 用)

外部注册中心

K8s 外部(或跨集群)场景,或 Java 微服务传统生态,仍会使用独立注册中心:

注册流程

服务启动
   │
   ▼
向注册中心注册(IP:Port + 元数据)
   │
   ▼
注册中心维护服务列表 + 健康检查
   │
   ▼
调用方从注册中心获取实例列表
   │
   ▼
本地负载均衡选择一个实例调用

主流注册中心对比

注册中心一致性健康检查适用生态特点
NacosAP / CP 可切换TCP / HTTP / 心跳Spring Cloud / Dubbo同时支持配置中心
ConsulCP(Raft)多维度Hashicorp / 多语言自带 Service Mesh
EurekaAP心跳Spring Cloud简单,已不再维护
ZookeeperCP(ZAB)Session 超时Dubbo重量级,运维复杂
etcdCP(Raft)LeaseK8s 内置不建议单独用作注册中心

Nacos 架构

服务启动
   │
   ▼
Nacos Server(集群部署)
   │
   ├── 注册表(服务名 → 实例列表)
   ├── 健康检查(定时心跳,超时剔除)
   └── 配置中心(动态配置下发)
   │
   ▼
消费方通过 Nacos SDK 获取实例
   │
   ▼
Ribbon / Spring LoadBalancer 本地选择实例

健康检查机制

机制说明
心跳续约服务每隔 N 秒向注册中心发送心跳,超时剔除
主动探测注册中心主动 HTTP / TCP 探测服务健康状态
K8s ReadinessPod 未就绪时从 Endpoint 移除,不接收流量

客户端 vs 服务端负载均衡

客户端负载均衡(Spring Cloud Ribbon / gRPC LB):

消费方
  │ 从注册中心拉取实例列表缓存本地
  │
  ├── 实例 A
  ├── 实例 B(选择)
  └── 实例 C

优点:无中间层,延迟低;缺点:每个客户端都要实现负载均衡逻辑。

服务端负载均衡(K8s Service / Nginx):

消费方 → Service(VIP)→ kube-proxy 转发到 Pod

优点:客户端无感知;缺点:多一跳,kube-proxy 是代理瓶颈。

配置中心(与注册中心结合)

Nacos、Consul 等同时承担配置中心职责:

配置变更(控制台 / Git)
   │
   ▼
配置中心
   │ 长轮询 / 推送
   ▼
服务实例(动态刷新配置,无需重启)

Java 实战(Spring Cloud)