by shihang.mai
1. 随机
- 将所有需要负载均衡的机器抽象成对象,放入list
- 利用new Random().nextInt(configs.size())获取随机下标
- 从list中获取目标机器
//随机算法
public class RandomLoadbalanceStrategy implements LoadbalanceStrategy{
//ProviderConfig-需要负载均衡的对象,例如10台机,那么这个list就有10个ProviderConfig对象
//Object不用管
@Override
public ProviderConfig select(List<ProviderConfig configs, Object object) {
int index = new Random().nextInt(configs.size());
return configs.get(index);
}
}
2. 加权随机算法
- 将所有需要负载均衡的机器抽象成对象,放入list
- 根据权重和list重新构建new list
- new Random().nextInt(newConfigs.size()-1)获取随机下标;
- 从new list中获取目标机器
public class WeightRandomLoadbalanceStrategy implements LoadbalanceStrategy{
@Override
public ProviderConfig select(List<ProviderConfig configs, Object object) {
List<ProviderConfig newConfigs = new ArrayList<();
for(ProviderConfig config:configs){
for(int i = 0; i< config.getWeight(); i++){
newConfigs.add(config);
}
}
int index = new Random().nextInt(newConfigs.size()-1);
return newConfigs.get(index);
}
}
3. 轮询
- 将所有需要负载均衡的机器抽象成对象,放入list
- 用一个Map<String,Integer存储<接口名,调用次数,目的为了每个接口进行负载均衡
- 获取当前调用接口的次数,用次数%list.size,获取此次调用的下标
- 从list中获取目标机器
public class PollingLoadbalanceStrategy implements LoadbalanceStrategy {
//使用一个Map来缓存每类应用的轮询索引
private Map<String,Integer indexMap = new ConcurrentHashMap<();
public ProviderConfig select(List<ProviderConfig configs, Object object){
Integer index = indexMap.get(getKey(configs.get(0)));
if(index == null){
index = 0;
}
else {
index++;
}
int i = index%configs.size();
indexMap.put(getKey(configs.get(0)),index);
return configs.get(i);
}
public String getKey(ProviderConfig config){
return config.getInterfaceName();
}
}
4. 加权轮询
- 将所有需要负载均衡的机器抽象成对象,放入list
- 用一个Map<String,Integer存储<接口名,调用次数,目的为了每个接口进行负载均衡
- 根据权重和list重新构建new list
- 获取当前调用接口的次数,用次数%list.size,获取此次调用的下标
- 从new list中获取目标机器
public class WeightPollingLoadbalanceStrategy implements LoadbalanceStrategy {
private Map<String,Integer indexMap = new ConcurrentHashMap<();
List<ProviderConfig newConfigs = null;
public ProviderConfig select(List<ProviderConfig configs, Object object){
if(newConfigs==null){
newConfigs = new ArrayList<();
for(ProviderConfig config:configs){
for(int i = 0; i< config.getWeight(); i++){
newConfigs.add(config);
}
}
}
Integer index = indexMap.get(getKey(configs.get(0)));
if(index == null){
index = 0;
}
else {
index++;
}
int i = index%newConfigs.size();
indexMap.put(getKey(configs.get(0)),index);
return newConfigs.get(i);
}
public String getKey(ProviderConfig config){
return config.getInterfaceName();
}
}
5. 最小时延算法
- 将所有需要负载均衡的机器抽象成对象,放入list,包括延时时间
- 排序取第一个获取目标机器
public class LeastActiveLoadbalanceStrategy implements LoadbalanceStrategy{
public ProviderConfig select(List<ProviderConfig configs, Object object){
ProviderConfig[] registryConfigs= new ProviderConfig[configs.size()];
configs.toArray(registryConfigs);
Arrays.sort(registryConfigs,(x,y)-{
if(x.getCallTime()<y.getCallTime()){
return -1;
}else if(x.getCallTime()==y.getCallTime()){
return 0;
}else{
return 1;
}
});
return registryConfigs[0];
}
}
6. 一致性哈希
- 将所有需要负载均衡的机器抽象成对象,放入list
- 为解决数据倾斜问题,每个节点虚拟化出多个节点,即如果有10个节点,那么每个节点+1-5 做hash,形成50个节点
- 这些节点全部放入TreeMap
- 当有请求过来时,将这个请求也hash,在TreeMap中找到最近的目标机器
public class UniformityHashLoadbalanceStrategy implements LoadbalanceStrategy{
private static final int VIRTUAL_NODES = 5;
SortedMap<Integer, ProviderConfig sortedMap = null;
public ProviderConfig select(List<ProviderConfig configs, Object object){
if(null==sortedMap){
sortedMap = new TreeMap();
for(ProviderConfig config:configs){
for(int j = 0; j < VIRTUAL_NODES; j++){
sortedMap.put(caculHash(getKey(config.getHost(),config.getPort(),"&&node"+j)),config);
}
}
}
System.out.println(sortedMap);
//需要请求的地址hash
Integer requestHashcCode = caculHash((String)object);
SortedMap<Integer, ProviderConfig subMap = sortedMap.subMap(requestHashcCode,Integer.MAX_VALUE);
ProviderConfig result= null;
if(subMap.size() != 0){
Integer index = subMap.firstKey();
result = subMap.get(index);
}
else{
result = sortedMap.get(0);
}
//// 打印测试数据
new PrintResult(sortedMap,requestHashcCode).print();
/////
return result;
}
private String getKey(String host,int port,String node){
return new StringBuilder().append(host).append(":").append(port).append(node).toString();
}
private int caculHash(String str){
/* int hashCode = str.hashCode();
hashCode = (hashCode<0)?(-hashCode):hashCode;
return hashCode;*/
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;
// 如果算出来的值为负数则取其绝对值
if (hash < 0)
hash = Math.abs(hash);
return hash;
}
}
//用于打印测试数据
//@Data
class PrintResult{
private boolean flag =false;
private SortedMap<Integer, ProviderConfig sortedMap;
private int requestHashcCode;
public PrintResult(SortedMap<Integer, ProviderConfig sortedMap, int requestHashcCode) {
this.sortedMap = sortedMap;
this.requestHashcCode = requestHashcCode;
}
public void print(){
sortedMap.forEach((k,v)-{
if( (false == flag) && ( k requestHashcCode)){
System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
System.out.println("hashcode: " + k + " " + v.getHost()+":"+v.getPort());
if( (false == flag) && ( k requestHashcCode)){
System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
flag = true;
}
});
System.out.println("------------------请求的hashcode:"+requestHashcCode);
}
}
网友评论