服务注册与发现
微服务动态部署,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 + 元数据)
│
▼
注册中心维护服务列表 + 健康检查
│
▼
调用方从注册中心获取实例列表
│
▼
本地负载均衡选择一个实例调用
主流注册中心对比
| 注册中心 | 一致性 | 健康检查 | 适用生态 | 特点 |
|---|---|---|---|---|
| Nacos | AP / CP 可切换 | TCP / HTTP / 心跳 | Spring Cloud / Dubbo | 同时支持配置中心 |
| Consul | CP(Raft) | 多维度 | Hashicorp / 多语言 | 自带 Service Mesh |
| Eureka | AP | 心跳 | Spring Cloud | 简单,已不再维护 |
| Zookeeper | CP(ZAB) | Session 超时 | Dubbo | 重量级,运维复杂 |
| etcd | CP(Raft) | Lease | K8s 内置 | 不建议单独用作注册中心 |
Nacos 架构
服务启动
│
▼
Nacos Server(集群部署)
│
├── 注册表(服务名 → 实例列表)
├── 健康检查(定时心跳,超时剔除)
└── 配置中心(动态配置下发)
│
▼
消费方通过 Nacos SDK 获取实例
│
▼
Ribbon / Spring LoadBalancer 本地选择实例
健康检查机制
| 机制 | 说明 |
|---|---|
| 心跳续约 | 服务每隔 N 秒向注册中心发送心跳,超时剔除 |
| 主动探测 | 注册中心主动 HTTP / TCP 探测服务健康状态 |
| K8s Readiness | Pod 未就绪时从 Endpoint 移除,不接收流量 |
客户端 vs 服务端负载均衡
客户端负载均衡(Spring Cloud Ribbon / gRPC LB):
消费方
│ 从注册中心拉取实例列表缓存本地
│
├── 实例 A
├── 实例 B(选择)
└── 实例 C
优点:无中间层,延迟低;缺点:每个客户端都要实现负载均衡逻辑。
服务端负载均衡(K8s Service / Nginx):
消费方 → Service(VIP)→ kube-proxy 转发到 Pod
优点:客户端无感知;缺点:多一跳,kube-proxy 是代理瓶颈。
配置中心(与注册中心结合)
Nacos、Consul 等同时承担配置中心职责:
配置变更(控制台 / Git)
│
▼
配置中心
│ 长轮询 / 推送
▼
服务实例(动态刷新配置,无需重启)