public class Instance {
private String ip;
private String port;
public Instance(String ip, String port) {
this.ip = ip;
this.port = port;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
}
public interface LoadBalancer {
/**
*
* @param instances zk拉取的服务地址列表
* @param address 本地客户端的服务地址ip
* @return 调用的远程服务器的ip+port
*/
Instance select(List<Instance> instances , String address);
}
随机算法
public class RandomLoadBalancer implements LoadBalancer{
@Override
public Instance select(List<Instance> instances , String address) {
return instances.get(new Random().nextInt(instances.size()));
}
}
轮询算法
public class RoundRobinLoadBalancer implements LoadBalancer{
private int index = 0;
@Override
public Instance select(List<Instance> instances , String address) {
return index < instances.size() ? instances.get(index++) : instances.get(0);
}
}
一致性hash算法
用于rpc项目中:
当客户端拉取到服务地址列表时进行一致性hash负载均衡实现
两个map进行映射
TreeMap(虚拟节点:真实节点的ip)
HashMap (真实节点的ip:真实节点的实例)
参数VIRTUAL_NODES:自定义虚拟节点的个数
public class IpHashLoadBalancer implements LoadBalancer{
@Override
public Instance select(List<Instance> instances , String address) {
ConsistentHash consistentHash = new ConsistentHash(instances, 100);
HashMap<String, Instance> map = consistentHash.map;
return map.get(consistentHash.getServerIp(address));
}
}
class ConsistentHash{
//key:虚拟节点的hash
//value:真实的服务地址ip
private static TreeMap<Integer,String> vnodeToIpMap = new TreeMap<>();
//key:真实的服务地址ip
//value:服务器实例 Instance(IP+PORT)
public static HashMap<String,Instance> map = new HashMap<>();
private static int VIRTUAL_NODES = 160;//虚拟节点个数默认160
private static List<Instance> instances;//服务地址列表
private static Set<Integer> set = new HashSet<>();//hash去重set
public ConsistentHash(List<Instance> instances , int VIRTUAL_NODES) {
instances = instances;
VIRTUAL_NODES = VIRTUAL_NODES;
}
static {
for(Instance instance : instances){
String ip = instance.getIp();
map.put(ip,instance);
for (int i = 0; i < VIRTUAL_NODES; i++) {
int hash = getHash(ip + "#" + i);
while (set.contains(hash)){//防止小概率事件
hash = getHash(ip + "#" + i + new Random().nextInt(100));
}
set.add(hash);
vnodeToIpMap.put(hash,ip);
}
}
}
//获取ip地址
public String getServerIp(String clientInfo){
int hash = getHash(clientInfo);
//key > hash 的 TreeMap
SortedMap<Integer, String> subMap = vnodeToIpMap.tailMap(hash);
Integer nodeIndex = subMap.firstKey();
return nodeIndex == null ?
vnodeToIpMap.get(vnodeToIpMap.firstKey())
: vnodeToIpMap.get(nodeIndex);
}
private static int getHash(String str){
final int p = 16777619;
int hash = (int) 2166136261L;
for (int i = 0; i < str.length(); i++) {
hash = (hash ^ str.charAt(i)) * p;
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
hash = Math.abs(hash);
}
return hash;
}
}