Java 实现6中负载均衡算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29777207/article/details/88826893

1、完全随机算法

缺点:所有服务器的访问概率都是相同的。

package com.example.demo.core.random;

import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * 负载均衡算法
 * 完全随机算法
 */
public class RandomServer {

    public static List<String> list = Arrays.asList("10.180.11.126:8888","10.180.11.128:8888","10.180.11.130:8888");

    static Random random = new Random();

    public static String getServer() {
        int number = random.nextInt(list.size());
        return list.get(number);
    }

    public static void main(String[] args) {
        for(int i = 0; i < 15; i++) {
            System.out.println(getServer());
        }
    }
}

2、加权随机算法

场景:当有的服务器性能高,可以让随机到此服务器的可能性增大

缺点:权重低的服务器可能很长一段时间都访问不到3

package com.example.demo.core.random;

import java.util.*;

/**
 * 负载均衡算法
 *
 * 如果某一台服务器性能比较高,设置访问的权重高一点
 *
 * 加权随机算法
 */
public class WeightRandomServer {

    public static Map<String,Integer> map = new HashMap<>();

    static {
        map.put("10.180.11.126:8888",2);
        map.put("10.180.11.128:8888",7);
        map.put("10.180.11.130:8888",1);
    }

    static Random random = new Random();

    /**
     * 当权重设置过大时,list容易被撑爆
     * @return
     */
    public static String getServer() {

        List<String> list = new ArrayList<>();

        for(Map.Entry<String,Integer> entry: map.entrySet()) {

            //根据权重,决定向list中添加几次
            for(int i = 0; i < entry.getValue(); i++) {

                list.add(entry.getKey());
            }
        }
        //list的大小
        int weight = map.values().stream().mapToInt(p -> p).sum();

        int number = random.nextInt(weight);

        return list.get(number);
    }


    /**
     * 优化后
     * @return
     */
    public static String getServer1() {
        //计算总权值
        int weight = map.values().stream().mapToInt(p -> p).sum();

        //随机一个随机数
        int index = random.nextInt(weight);

        //遍历  服务  map
        for(Map.Entry<String,Integer> entry : map.entrySet()) {
            //如果权重大于  索引
            if(entry.getValue() >= index) {
                // 返回这个服务
                return entry.getKey();
            }
            //否则,索引 = 当前索引 - 当前服务的权重
            index = index - entry.getValue();
        }
        return "";
    }

    public static void main(String[] args) {

        for(int i = 0; i < 15; i++) {

            //System.out.println(getServer());
            System.out.println(getServer1());
        }
    }
}

3、完全轮询算法

缺点:从头到尾轮询一遍,不能根据服务器性能设置权重

package com.example.demo.core.poll;

import java.util.Arrays;
import java.util.List;

/**
 * 完全轮询算法
 */
public class PollServer {
    public static List<String> list = Arrays.asList("10.180.11.126:8888","10.180.11.128:8888","10.180.11.130:8888");

    static int index;

    public static String getServer() {
        if(index == list.size()) {
            index = 0;
        }
        return list.get(index++);
    }

    public static void main(String[] args) {

        for(int i = 0; i < 15; i++) {

            System.out.println(getServer());
        }
    }
}

4、加权轮询算法

有点:可以根据服务器性能设置访问权重

缺点:可能某个服务器权重大,长时间执行,遇到耗时大的请求,压力会很大

package com.example.demo.core.poll;

import java.util.HashMap;
import java.util.Map;

/**
 * 加权轮询算法
 * 实际中可能遇到某个服务器压力较大,长时间执行。
 */
public class WeightPollServer {

    public static Map<String,Integer> map = new HashMap<>();

    static {
        map.put("10.180.11.126:8888",2);
        map.put("10.180.11.128:8888",7);
        map.put("10.180.11.130:8888",5);
    }

    static int index;

    public static String getServer() {
        int weight = map.values().stream().mapToInt( p -> p).sum();
        int number = (index++) % weight;
        for(Map.Entry<String,Integer> entry : map.entrySet()) {
            if(entry.getValue() >= number) {
                return entry.getKey();
            }
            number = number - entry.getValue();
        }
        return "";
    }

    public static void main(String[] args) {

        for(int i = 0; i < 15; i++) {
            System.out.println(getServer());
        }
    }
}

5、平滑加权轮询算法

优点:根据权重分配服务,同时又保证权重低的服务可以被访问到

缺点:集群环境下,同一个用户访问无法分流到固定一台机器

package com.example.demo.core.smooth;

/**
 * 平滑加权
 */
public class SmoothWeight {

    private int weight;

    private int currentWeight;

    private String address;


    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getCurrentWeight() {
        return currentWeight;
    }

    public void setCurrentWeight(int currentWeight) {
        this.currentWeight = currentWeight;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public SmoothWeight(int weight, int currentWeight, String address) {
        this.weight = weight;
        this.currentWeight = currentWeight;
        this.address = address;
    }
}
package com.example.demo.core.smooth;

import java.util.HashMap;
import java.util.Map;

/**
 * 平滑加权轮询算法
 */
public class SmoothWeightPollServer {


    public static Map<String,SmoothWeight> map = new HashMap<>();

    static {
        map.put("10.180.11.126:8888",new SmoothWeight(5,5,"10.180.11.126:8888"));
        map.put("10.180.11.128:8888",new SmoothWeight(2,2,"10.180.11.128:8888"));
        map.put("10.180.11.130:8888",new SmoothWeight(4,4,"10.180.11.130:8888"));
    }

    public static String getServer() {

        SmoothWeight maxSmoothWeight = null;

        int weight = map.values().stream().mapToInt(SmoothWeight :: getWeight).sum();

        for(Map.Entry<String,SmoothWeight> entry : map.entrySet()) {

            SmoothWeight currentSmoothWeight = entry.getValue();

            if(maxSmoothWeight == null || currentSmoothWeight.getCurrentWeight() > maxSmoothWeight.getCurrentWeight()) {
                maxSmoothWeight = currentSmoothWeight;
            }
        }
        assert maxSmoothWeight != null;
        maxSmoothWeight.setCurrentWeight(maxSmoothWeight.getCurrentWeight() - weight);
        for(Map.Entry<String,SmoothWeight> entry : map.entrySet()) {

            SmoothWeight currentSmoothWeight = entry.getValue();

            currentSmoothWeight.setCurrentWeight(currentSmoothWeight.getCurrentWeight() + currentSmoothWeight.getWeight());
        }

        return maxSmoothWeight.getAddress();
    }


    public static void main(String[] args) {

        for(int i = 0; i < 15; i++) {
            System.out.println(getServer());
        }
    }
}

6、哈希负载算法

package com.example.demo.core.hash;

import java.util.Arrays;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * hash负载算法
 * 在一个集群环境下,让同一个用户的访问,分流到固定的一台机器上
 */
public class HashServer {

    public static List<String> list = Arrays.asList("10.180.11.126:8888","10.180.11.128:8888","10.180.11.130:8888");

    public static String getServer(String client){
        int nodeCount = 40;

        TreeMap<Integer,String> treeMap = new TreeMap<>();

        for(String s : list) {
            for(int i = 0; i < nodeCount; i++) {
                treeMap.put((s + "address:" + i).hashCode(), s);
            }
        }

        SortedMap<Integer,String> sortedMap = treeMap.tailMap(client.hashCode());

        Integer firstHash = (sortedMap.size() > 0) ? sortedMap.firstKey() : treeMap.firstKey();

        return treeMap.get(firstHash);
    }

    public static void main(String[] args) {

        for(int i = 0; i < 100; i++) {
            System.out.println(getServer("用户:" + i + "访问"));
        }
    }

}

猜你喜欢

转载自blog.csdn.net/qq_29777207/article/details/88826893