您的位置:首页 > 编程语言

参考dubbo 利用hash一致性做负载均衡[代码记录,供以后参考]

2016-10-27 14:22 211 查看

1.定义loadbalance接口方法

package com.gj.moto.base.clustering.loadbalance;

import java.util.List;

public interface LoadBalance {
String select(List<String> servers, String type, String key);
}


servers:共有多少台服务节点;
type:表示对哪类服务做hash一致性,可同时对多种服务做hash一致性算法;
key:hash一致性的关键因子,用其hash值动态找出目标服务节点;

2.定义基类,做一些简单参数的过滤

import java.util.List;

public abstract class AbstractLoadBalance implements LoadBalance {

@Override
public String select(List<String> servers, String type, String key) {
if (servers == null || servers.isEmpty()) {
return null;
}
if (servers.size() == 1) {
return servers.get(0);
}

return doSelect(servers, type, key);
}

protected abstract String doSelect(List<String> servers, String type,
String key);

}

3.hash一致性负载均衡实现算法

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class ConsistentHashLoadBalance extends AbstractLoadBalance {
private final ConcurrentMap<String, ConsistentHashSelector> selectors = new ConcurrentHashMap<String, ConsistentHashSelector>();

@Override
protected String doSelect(List<String> servers, String type, String key) {
int identityHashCode = System.identityHashCode(servers);
ConsistentHashSelector selector = selectors.get(type);
if (selector == null
|| selector.getIdentityHashCode() != identityHashCode) {
selectors.put(type, new ConsistentHashSelector(servers, type));
selector = selectors.get(type);
}
return selector.select(key);

}

private static final class ConsistentHashSelector {

private final TreeMap<Long, String> virtualServers;

private final int replicaNumber;

private final int identityHashCode;

public ConsistentHashSelector(List<String> servers, String type) {
this.virtualServers = new TreeMap<Long, String>();
this.identityHashCode = System.identityHashCode(servers);
this.replicaNumber = 160;
for (String invoker : servers) {
for (int i = 0; i < replicaNumber / 4; i++) {
byte[] digest = md5(type + invoker + i);
for (int h = 0; h < 4; h++) {
long m = hash(digest, h);
virtualServers.put(m, invoker);
}
}
}
}

public int getIdentityHashCode() {
return identityHashCode;
}

public String select(String key) {
byte[] digest = md5(key);
String invoker = sekectForKey(hash(digest, 0));
return invoker;
}

private String sekectForKey(long hash) {
String invoker;
Long key = hash;
if (!virtualServers.containsKey(key)) {
SortedMap<Long, String> tailMap = virtualServers.tailMap(key);
if (tailMap.isEmpty()) {
key = virtualServers.firstKey();
} else {
key = tailMap.firstKey();
}
}
invoker = virtualServers.get(key);
return invoker;
}

private long hash(byte[] digest, int number) {
return (((long) (digest[3 + number * 4] & 0xFF) << 24)
| ((long) (digest[2 + number * 4] & 0xFF) << 16)
| ((long) (digest[1 + number * 4] & 0xFF) << 8) | (digest[0 + number * 4] & 0xFF)) & 0xFFFFFFFFL;
}

private byte[] md5(String value) {
MessageDigest md5;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e.getMessage(), e);
}
md5.reset();
byte[] bytes = null;
try {
bytes = value.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e.getMessage(), e);
}
md5.update(bytes);
return md5.digest();
}
}

}


这样基本的算法就已经完成。
hash一致性的思想可以去百度下,算法底层实现原理这里后面再补充。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  负载均衡 dubbo