最近在看负载均衡,然后看到了权重负载这个概念,然后实现了一个单机的版本。
· 前言
对于分布式的系统,负载均衡是必不可少的,所谓的负载均衡就是将流量按照一定的规则分发到对应的服务上,常见的有轮询、随机以及权重,那我接下来就来讲讲权重负载。
· 权重
在生产环节中往往机器的配置情况是不太一样的,那么配置高的机器就需要承担更多的流量,权重的负载应运而生。
· 实现
首先说说思路,思路是采用一个队列,队列里面的内容是按照权重生成的,比如现在有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;
}
}
}
· 实现
测试结果:
好了,分享到此结束啦,我们下次再见!