负载均衡-随机权重

101 阅读2分钟

最近在看负载均衡,然后看到了权重负载这个概念,然后实现了一个单机的版本。

· 前言

对于分布式的系统,负载均衡是必不可少的,所谓的负载均衡就是将流量按照一定的规则分发到对应的服务上,常见的有轮询、随机以及权重,那我接下来就来讲讲权重负载。

· 权重

在生产环节中往往机器的配置情况是不太一样的,那么配置高的机器就需要承担更多的流量,权重的负载应运而生。

· 实现

首先说说思路,思路是采用一个队列,队列里面的内容是按照权重生成的,比如现在有A、B、C、D四台机器权重分别是10、40、30、20,其实这个就是每台机器对应总流量的比例,比如A就应该分配到10%的流程,那么队列里面要存储什么呢?答案是对应的服务id(服务的标识),这里假设A、B、C、D就是服务id,那么就是说队列里面有10个A、40个B、30个C、20个D,然后为了均衡可以进行一下清洗,打乱顺序,接下来看看代码实现吧。

public class WeightBalancer {

    private static final Queue<String> QUEUE = new LinkedBlockingQueue<>();

    public WeightBalancer(List<Node> nodes) {
        if (nodes != null && nodes.size() > 0) {
            final int sum = nodes.stream().mapToInt(Node::getWeight).sum();
            if (sum != 100) {
                throw new RuntimeException("权重设置异常!");
            }
            List<String> temp = new ArrayList<>();
            for (Node node : nodes) {
                final Integer weight = node.weight;
                for (int i = 0; i < weight; i++) {
                    temp.add(node.id);
                }
            }
            // 洗牌
            Collections.shuffle(temp);
            QUEUE.addAll(temp);
        }
    }

    public String getServerId() {
        final String poll = QUEUE.poll();
        QUEUE.add(poll);
        return poll;
    }

    public static void main(String[] args) {
        List<Node> nodes = new ArrayList<>();
        nodes.add(new Node("A", 10));
        nodes.add(new Node("B", 40));
        nodes.add(new Node("C", 30));
        nodes.add(new Node("D", 20));
        final WeightBalancer weightBalancer = new WeightBalancer(nodes);
        Map<String, Integer> statistics = new ConcurrentHashMap<>();
        for (int n = 0; n < 10000; n++) {
            final String serverId = weightBalancer.getServerId();

            System.out.println(serverId);

            Integer count = statistics.get(serverId);
            if (count == null) {
                statistics.put(serverId, 1);
            } else {
                statistics.put(serverId, ++count);
            }
        }
        for (Map.Entry<String, Integer> entry : statistics.entrySet()) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
    }

    public static class Node {
        /**
         * 服务id
         */
        private String id;

        /**
         * 权重
         */
        private Integer weight;

        public Node(String id, Integer weight) {
            this.id = id;
            this.weight = weight;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public Integer getWeight() {
            return weight;
        }

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

}

· 实现

测试结果:

截屏2022-07-21 21.38.57.png

好了,分享到此结束啦,我们下次再见!