9.4.5 客户端负载均衡与就近访问策略
5. 客户端负载均衡与就近访问策略#
客户端负载均衡由服务调用方在本地完成实例选择:订阅实例列表→维护本地缓存与健康状态→按策略选择实例→失败重试或切换。适合结合业务上下文做精细化控制与就近访问。
原理草图#
负载均衡策略与就近访问要点#
- 轮询/加权轮询:按权重分配流量,适合实例性能差异大。
- 随机/加权随机:分布更均匀,避免周期性热点。
- 最少连接/最短响应:需收集实时指标,适合低延迟场景。
- 一致性哈希:保持会话/缓存命中,减少跨实例抖动。
- 区域优先:同集群/同机房优先,跨地域降级。
- 标签路由:按 metadata 标记灰度、金丝雀、版本隔离。
安装与基础示例(Nacos + Java 客户端)#
1)启动 Nacos(单机)
# 假设已下载 nacos-server-2.x.tar.gz
tar -xzf nacos-server-2.x.tar.gz -C /opt/
cd /opt/nacos/bin
# 单机模式启动
./startup.sh -m standalone
# 预期:8080 端口启动
ss -lntp | grep 8848
2)注册服务实例并设置 metadata(示例 HTTP API)
# 注册服务并标注 region/zone/weight
curl -X POST "http://127.0.0.1:8848/nacos/v1/ns/instance" \
-d "serviceName=order-service" \
-d "ip=10.0.1.10" \
-d "port=8081" \
-d "weight=2" \
-d "metadata.region=cn-hz" \
-d "metadata.zone=az1"
curl -X POST "http://127.0.0.1:8848/nacos/v1/ns/instance" \
-d "serviceName=order-service" \
-d "ip=10.0.2.20" \
-d "port=8081" \
-d "weight=1" \
-d "metadata.region=cn-sh" \
-d "metadata.zone=az2"
3)客户端负载均衡与就近访问示例(Spring Cloud Alibaba)
- 配置文件 application.yml
spring:
application:
name: order-client
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
# 就近访问:优先同集群
cluster-name: cn-hz
# 元数据过滤:只选择标记为 prod 的实例
metadata:
env: prod
loadbalancer:
# 开启权重优先策略(基于 Nacos 权重)
nacos:
enabled: true
- Java 代码(选择实例 + 自定义就近策略简化示例)
// 伪代码,展示实例过滤与权重选择逻辑
List<Instance> instances = namingService.selectInstances("order-service", true);
// 1) 优先同集群/同zone
List<Instance> sameCluster = instances.stream()
.filter(i -> "cn-hz".equals(i.getClusterName()))
.collect(Collectors.toList());
// 2) 如果同集群为空,降级到所有实例
List<Instance> candidates = sameCluster.isEmpty() ? instances : sameCluster;
// 3) 按权重随机选择
Instance selected = WeightRandom.selectByWeight(candidates);
// 4) 发送请求
命令验证与预期效果#
# 查询服务实例列表
curl "http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=order-service"
# 预期:返回包含 region/zone/weight 的实例信息
# 当客户端 cluster-name=cn-hz 时,优先选择 cn-hz 集群实例
失败重试与熔断示例(配置)#
# application.yml
resilience4j:
retry:
instances:
orderService:
maxAttempts: 3
waitDuration: 300ms
enableExponentialBackoff: true
exponentialBackoffMultiplier: 2
circuitbreaker:
instances:
orderService:
failureRateThreshold: 50
waitDurationInOpenState: 5s
slidingWindowSize: 10
排错要点与命令#
1)客户端未命中就近实例
- 检查实例元数据与集群名是否一致
# 查看实例详情
curl "http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=order-service" \
| jq '.hosts[] | {ip,clusterName,metadata}'
- 检查客户端配置
cluster-name是否正确
grep -R "cluster-name" -n config/ application.yml
2)实例列表为空
- 检查 Nacos 注册是否成功、心跳是否正常
# 查看 Nacos 日志
tail -f /opt/nacos/logs/nacos.log
3)负载不均或热点
- 检查权重设置与策略
# 修改权重
curl -X PUT "http://127.0.0.1:8848/nacos/v1/ns/instance" \
-d "serviceName=order-service" \
-d "ip=10.0.1.10" \
-d "port=8081" \
-d "weight=5"
练习#
1)注册三台实例,设置不同 region/zone/weight,验证客户端优先同集群。
2)模拟一台实例下线,观察客户端重试与熔断是否生效。
3)将负载策略从权重随机切换为一致性哈希,比较缓存命中率变化。