myrpc 学习笔记-007 负载均衡

项目地址 欢迎访问

https://gitee.com/longlong5/myrpc

笔记总览 myrpc 学习笔记-001 实现简易版 rpc myrpc 学习笔记-002 配置加载 myrpc 学习笔记-003 Mock 服务代理 myrpc 学习笔记-004 序列化实现和 SPI 机制 myrpc 学习笔记-005 注册中心 myrpc 学习笔记-006 自定义协议 myrpc 学习笔记-007 负载均衡 myrpc 学习笔记-008 重试机制 myrpc 学习笔记-009 容错机制 myrpc 学习笔记-0010 启动机制和注解驱动

架构图v7.0.0

  • 实现负载均衡
  • 支持 轮询 随机 等负载均衡策略
  • 支持自定义策略

v7.0.0.png

(1)轮询策略

RoundRobinLoadBalancer

原理:按顺序依次分配请求,使用原子类 AtomicInteger保证多线程安全。

java
复制代码
@Slf4j public class RoundRobinLoadBalancer implements LoadBalancer { // 原子计数器,保证线程安全 private final AtomicInteger currentIndex = new AtomicInteger(0); @Override public ServiceMetaInfo select(Map<String, Object> requestParams, List<ServiceMetaInfo> serviceMetaInfoList) { log.info("当前负载均衡策略: 轮询"); if (serviceMetaInfoList.isEmpty()) return null; int size = serviceMetaInfoList.size(); if (size == 1) return serviceMetaInfoList.get(0); // 取模轮询:计数器自增后对服务数量取模 int index = currentIndex.getAndIncrement() % size; return serviceMetaInfoList.get(index); } }

(2)随机策略

RandomLoadBalancer

原理:使用随机数生成器,从服务列表中随机选择一个节点。

java
复制代码
@Slf4j public class RandomLoadBalancer implements LoadBalancer { private final Random random = new Random(); @Override public ServiceMetaInfo select(Map<String, Object> requestParams, List<ServiceMetaInfo> serviceMetaInfoList) { log.info("当前负载均衡策略: 随机"); int size = serviceMetaInfoList.size(); if (size == 0) return null; if (size == 1) return serviceMetaInfoList.get(0); // 随机生成下标 return serviceMetaInfoList.get(random.nextInt(size)); } }

(3)一致性哈希策略

ConsistentHashLoadBalancer

原理

  • 构建虚拟节点环,解决数据倾斜问题
  • 使用 TreeMap 模拟哈希环,ceilingEntry 寻找匹配节点
  • 同一个请求参数始终命中同一个服务节点,适合有状态服务
java
复制代码
@Slf4j public class ConsistentHashLoadBalancer implements LoadBalancer { // 一致性Hash环,TreeMap天然有序 private final TreeMap<Integer, ServiceMetaInfo> virtualNodes = new TreeMap<>(); // 虚拟节点数量(提高分布均匀性) private static final int VIRTUAL_NODE_NUM = 100; @Override public ServiceMetaInfo select(Map<String, Object> requestParams, List<ServiceMetaInfo> serviceMetaInfoList) { log.info("当前负载均衡策略: 一致性哈希"); if (serviceMetaInfoList.isEmpty()) return null; // 1. 构建虚拟节点环 for (ServiceMetaInfo serviceMetaInfo : serviceMetaInfoList) { // 为每个真实节点创建100个虚拟节点 for (int i = 0; i < VIRTUAL_NODE_NUM; i++) { int hash = getHash(serviceMetaInfo.getServiceAddress() + "#" + i); virtualNodes.put(hash, serviceMetaInfo); } } // 2. 计算请求参数的哈希值 int hash = getHash(requestParams); // 3. 寻找大于等于当前hash的最近节点 Map.Entry<Integer, ServiceMetaInfo> entry = virtualNodes.ceilingEntry(hash); // 无匹配节点,返回环的第一个节点 if (entry == null) entry = virtualNodes.firstEntry(); return entry.getValue(); } // 哈希算法(可替换为FNV、MurmurHash等) private int getHash(Object key) { return key.hashCode(); } }

使用方式

  1. 配置指定策略
yaml
复制代码
rpc: loadBalancer: consistentHash
  1. 代码中调用
java
复制代码
// 获取负载均衡实例 LoadBalancer loadBalancer = LoadBalancerFactory.getLoadBalancer(rpcConfig.getLoadBalancer()); // 选择服务节点 ServiceMetaInfo selectedService = loadBalancer.select(requestParams, serviceMetaInfoList);
0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
longlong
下载 APP