服务注册发现与负载均衡
在微服务架构中,服务实例动态扩缩容,客户端无法硬编码地址。注册中心与负载均衡解决了"如何找到服务"和"如何分配流量"的核心问题。
1. 服务注册发现模式
客户端发现
┌─────────┐ ┌───────────────┐ ┌────────────┐
│ Service │ ←→ │ Registry │ │ │
│ A │ │ (Eureka,Consul)│ │ Service B │
└─────────┘ └───────────────┘ └────────────┘
↓ 查询并缓存实例列表 ↑
└─────────────────────────────→
Service A 自行决定访问哪个 B 实例
代表:Eureka、Consul Client、Nacos Client
服务端发现
┌─────────┐ ┌───────────────┐ ┌────────────┐
│ Service │ → │ Load Balancer │ → │ Service B │
│ A │ │ (Consul,Nginx)│ │ Instance │
└─────────┘ └───────────────┘ └────────────┘
A 只访问 LB 地址,由 LB 选择后端实例
代表:AWS ALB、Kubernetes Service、Nginx + Consul Template
2. 注册中心对比
| 特性 | Eureka | Consul | Nacos |
|---|---|---|---|
| 开发方 | Netflix | HashiCorp | 阿里巴巴 |
| 一致性协议 | AP(自我保护) | CP/AP 可选 | AP + raft CP |
| 健康检查 | Client 心跳 | HTTP/TCP/自定义 | TCP/HTTP/MYSQL |
| 多数据中心 | 弱支持 | 原生支持 | 支持 |
| 配置中心 | 无 | 简单 KV | 内置强大配置 |
| 生态 | Spring Cloud | 云原生 | Dubbo/Spring Cloud |
| 控制台 | 基础 | 完善 | 完善 |
Eureka 自我保护
网络分区时,Eureka 进入保护模式:不注销心跳过期的实例,优先保证可用性(AP)。
eureka:
server:
enable-self-preservation: true
renewal-percent-threshold: 0.85
Consul 服务网格
# 服务定义 + Sidecar 代理
service {
name = "order-service"
port = 8080
connect {
sidecar_service {}
}
}
Nacos 注册+配置一体化
spring:
cloud:
nacos:
discovery:
server-addr: nacos:8848
namespace: prod
config:
server-addr: nacos:8848
file-extension: yaml
3. 负载均衡算法
| 算法 | 机制 | 适用场景 |
|---|---|---|
| Round Robin | 轮询 | 实例性能相近 |
| Weighted Round Robin | 按权重轮询 | 异构实例 |
| Least Connections | 最少连接 | 长连接服务 |
| Least Response Time | 响应时间最低 | 性能敏感 |
| Random | 随机 | 简单、无状态 |
| Consistent Hash | 一致性哈希 | 缓存场景 |
| IP Hash | 源 IP 哈希 | 会话保持 |
一致性哈希
Hash Ring (0 ~ 2^32-1)
Node A ●----------------● Node B
/ \
Key 1 ● ● Key 2
Key 3 ● ● Node C
Key 4
Key 顺时针找最近的 Node,新增/删除只影响相邻区域
Ribbon 负载均衡规则
// Spring Cloud OpenFeign + Ribbon
@FeignClient(name = "order-service", configuration = FeignConfig.class)
public interface OrderClient { ... }
// IRule 实现
new RoundRobinRule(); // 轮询
new WeightedResponseTimeRule(); // 按响应时间加权
new RandomRule(); // 随机
4. Kubernetes 服务发现
Service + Endpoint
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector:
app: order
ports:
- port: 80
targetPort: 8080
# 集群内 DNS 解析
order-service.default.svc.cluster.local → Pod IPs
Headless Service
spec:
clusterIP: None # 直接返回 Pod IP 列表,用于 StatefulSet
高级流量管理(Istio)
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: order-route
spec:
http:
- route:
- destination:
host: order-service
subset: v1
weight: 90
- destination:
host: order-service
subset: v2
weight: 10
5. 高可用设计
| 策略 | 说明 |
|---|---|
| 多实例集群 | 注册中心本身多节点部署 |
| 客户端缓存 | 本地缓存服务列表,注册中心故障仍可调用 |
| 心跳保活 | 定期续约,及时剔除不健康实例 |
| 重试+退避 | 调用失败时自动切换实例 |
总结
| 维度 | 客户端发现 | 服务端发现 |
|---|---|---|
| 耦合 | 客户端依赖 SDK | 客户端无感知 |
| 灵活性 | 可自定义 LB 策略 | 集中管理 |
| 复杂度 | 客户端较重 | 需额外 LB 组件 |
| 典型 | Eureka + Ribbon | K8s Service + Istio |
选择注册中心时考虑:技术栈匹配、一致性需求、生态集成、运维复杂度。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。