Java implementation of NGINX smooth weighted polling algorithm

Preface

Recently, there was a scenario in the project where we needed to connect two third parties and compare the capabilities of the two third parties. At this time, we need to divert our traffic and determine the proportion of diverted traffic according to the configuration. That is, each request needs to be based on the configuration. To choose a third party and send the traffic there, I thought of Nginx's load balancing algorithm, which itself is also a traffic distribution algorithm.

NGINX smooth weighted polling algorithm

Several concepts involved in algorithms

weight:

Agreed weight, the weight of each node specified in the configuration file or initialization

effectiveWeight:

The effective weight is used when a node is abnormal and its weight is reduced. The initial value is weight. If a node abnormality is found during the communication process, it will be -1; then the node will be selected again. If the call is successful once, it will be +1 until the weight is restored;

currentWeight:

The current weight of the node is initialized to 0;

Java implementation

In the current implementation, effectiveWeight is not considered

Define nodes:

@Data
public class Node {
    /**
     * 节点名称
     */
    private String name;
    /**
     * 权重
     */
    private int weight;
    /**
     * 当前权重
     */
    private int currentWeight;
}

Smooth weighted polling algorithm implementation:

public class SmoothWeightPolling {
    /**
     * 所有负载均衡的节点集合
     */
    private List<Node> nodeList;
    /**
     * 为了提高计算的性能,在初始化的时候就把总权重计算出来
     */
    private int totalWeight;

    public SmoothWeightPolling(List<Node> nodeList) {
        if (null == nodeList || nodeList.isEmpty()) {
            throw new IllegalArgumentException("nodeList is null or empty");
        }
        this.nodeList = nodeList;
        for (Node node : nodeList) {
            totalWeight = totalWeight + node.getWeight();
        }
    }

    public Node getNode() {
        Node maxCurrentWeightNode = null;
        for (Node node : nodeList) {
            //计算每个节点的currentWeight = currentWeight + Weight;
            node.setCurrentWeight(node.getCurrentWeight() + node.getWeight());
            if (null == maxCurrentWeightNode) {
                maxCurrentWeightNode = node;
            } else if (maxCurrentWeightNode.getCurrentWeight() < node.getCurrentWeight()) {
                //选择所有节点中currentWeight最大的作为选中节点;
                maxCurrentWeightNode = node;
            }
        }
        //选中节点的currentWeight = currentWeight - totalWeight
        maxCurrentWeightNode.setCurrentWeight(maxCurrentWeightNode.getCurrentWeight() - totalWeight);
        return maxCurrentWeightNode;
    }

    public static void main(String[] args) {
        List<Node> nodeList = new ArrayList<>();
        Node node = new Node();
        node.setName("a");
        node.setWeight(4);
        nodeList.add(node);
        node = new Node();
        node.setName("b");
        node.setWeight(2);
        nodeList.add(node);
        node = new Node();
        node.setName("c");
        node.setWeight(1);
        nodeList.add(node);
        SmoothWeightPolling smoothWeightPolling = new SmoothWeightPolling(nodeList);
        for (int i = 0; i < 7 ; i++) {
            System.out.println("select node = " + smoothWeightPolling.getNode());
        }
    }
}

Output:

select node = Node(name=a, weight=4, currentWeight=-3)
select node = Node(name=b, weight=2, currentWeight=-3)
select node = Node(name=a, weight=4, currentWeight=-2)
select node = Node(name=c, weight=1, currentWeight=-3)
select node = Node(name=a, weight=4, currentWeight=-1)
select node = Node(name=b, weight=2, currentWeight=-2)
select node = Node(name=a, weight=4, currentWeight=0)

Guess you like

Origin blog.csdn.net/duzm200542901104/article/details/132358267
Recommended