rpc项目中的负载均衡算法
一致性hash算法(根据IP一致性hash)
一致性哈希策略的实现方式:我们先把服务列表中的地址进行哈希计算,把计算后的值放到哈希环上,接收到请求后,根据请求的固定属性值来进行哈希计算,然后根据请求的哈希值在哈希环上顺时针寻找服务地址的哈希值,寻找到哪个服务地址的哈希值,就把请求分配给哪个服务。
步骤:
-
首先获取到节点列表
-
根据节点列表得到每一个节点的hash值,同时在增加一些虚拟节点,比如原始服务节点上192.168.0.3 那么虚拟节点就是192.168.0.3#1 和192.168.0.3#2 注意所有节点计算hash值都是用string类型的hashcode方法
-
根据消费者的ip计算出消费者的节点请求的hash值,根据Map.tailMap()方法得到所有有大于 requestHash 的 key,取第一个
虚拟节点主要是解决服务节点hash分布不均匀的问题
/**
* 一致性哈希策略 Demo
*/
public class ConsistentHashingStrategy {
public static void main(String[] args) {
// 模拟 Server 地址列表
String[] serverList = {"192.168.0.15", "192.168.0.30", "192.168.0.45"};
// 新建 TreeMap 集合 ,以 Key,Value 的方式绑定 Hash 值与地址
SortedMap<Integer, String> serverHashMap = new TreeMap<>();
// 计算 Server 地址的 Hash 值
for (String address : serverList) {
int serverHash = Math.abs(address.hashCode());
// 绑定 Hash 值与地址
serverHashMap.put(serverHash, address);
}
// 模拟 Request 地址
String[] requestList = {"192.168.0.10", "192.168.0.20", "192.168.0.40", "192.168.0.50"};
// 计算 Request 地址的 Hash 值
for (String request : requestList) {
int requestHash = Math.abs(request.hashCode());
// 在 serverHashMap 中寻找所有大于 requestHash 的 key
SortedMap<Integer, String> tailMap = serverHashMap.tailMap(requestHash);
//如果有大于 requestHash 的 key, 第一个 key 就是离 requestHash 最近的 serverHash
if (!tailMap.isEmpty()) {
Integer key = tailMap.firstKey();
// 根据 key 获取 Server address
String address = serverHashMap.get(key);
System.out.println("请求 " + request + " 被分配给服务 " + address);
} else {
// 如果 serverHashMap 中没有比 requestHash 大的 key
// 则直接在 serverHashMap 取第一个服务
Integer key = serverHashMap.firstKey();
// 根据 key 获取 Server address
String address = serverHashMap.get(key);
System.out.println("请求 " + request + " 被分配给服务 " + address);
}
}
}
}
基于最小连接数的负载均衡算法()
服务提供者
注册临时节点到zookeeper 的时候增加一个data字段,初始化为0
/**
* 最小连接数策略 Demo
* Server 服务端注册地址
*/
消费者
在客户端的请求调用集群服务之前,先使用 Curator 获取 IMOOC_SERVER 下所有的临时节点,并寻找出 data 最小的临时节点,也就是最小连接数的服务。
在客户端发送请求时,我们可以让当前 Server 的请求会话数加 1,并更新到临时节点的 data,完成请求时,我们可以让当前 Server 的请求会话数减 1,并更新到临时节点的 data 。
/**
* 最小连接数策略 Demo
* Client 客户端发送请求
*/
