Load balancing series

01- Load Balancing Basics

02- Consistency Hash principle

03- Java implementation of consistent hash algorithm

04- Java implementation of load balancing algorithm

In this section we look at how to implement a load balancing framework.

The source code

Core Interface Definition

public interface ILoadBalance {

    /** * selects the next node ** returns the subscript *@paramContext *@returnResults *@since0.0.1 * /
    IServer select(final ILoadBalanceContext context);

}
Copy the code

1. Random strategy

public class LoadBalanceRandom extends AbstractLoadBalance{

    public LoadBalanceRandom(List<IServer> servers) {
        super(servers);
    }

    @Override
    protected IServer doSelect(ILoadBalanceContext context) {
        Random random = ThreadLocalRandom.current();
        int nextIndex = random.nextInt(servers.size());
        returnservers.get(nextIndex); }}Copy the code

2. Training in rotation

public class LoadBalanceRoundRobbin extends AbstractLoadBalance {

    /** ** *@since0.0.1 * /
    private final AtomicLong indexHolder = new AtomicLong();

    public LoadBalanceRoundRobbin(List<IServer> servers) {
        super(servers);
    }

    @Override
    protected IServer doSelect(ILoadBalanceContext context) {
        long index = indexHolder.getAndIncrement();
        int actual = (int) (index % servers.size());
        returnservers.get(actual); }}Copy the code

3. Weighted rotation training

This involves initializing the data and calculating the largest common divisor of the array.

public class LoadBalanceWeightRoundRobbin extends AbstractLoadBalance {

    /** ** *@since0.0.1 * /
    private final AtomicLong indexHolder = new AtomicLong();

    /** * Processed list *@since0.0.1 * /
    private final List<IServer> actualList = new ArrayList<>();

    public LoadBalanceWeightRoundRobbin(List<IServer> servers) {
        super(servers);

        // Initialize the real list
        this.init(servers);
    }

    @Override
    protected IServer doSelect(ILoadBalanceContext context) {
        long index = indexHolder.getAndIncrement();

        // Build based on real lists
        int actual = (int) (index % actualList.size());
        return actualList.get(actual);
    }

    /** * initialize *@paramServerList Service list *@since0.0.1 * /
    private void init(final List<IServer> serverList) {
        //1. Filter out machines with weight 0
        List<IServer> notZeroServers = CollectionUtil.filterList(serverList, new IFilter<IServer>() {
            @Override
            public boolean filter(IServer iServer) {
                return iServer.weight() <= 0; }});//2. Get the weight list
        List<Integer> weightList = CollectionUtil.toList(notZeroServers, new IHandler<IServer, Integer>() {
            @Override
            public Integer handle(IServer iServer) {
                returniServer.weight(); }});//3. Get the maximum weight
        int maxDivisor = MathUtil.ngcd(weightList);

        //4. Recalculate to build a weighted list
        for(IServer server : notZeroServers) {
            int weight = server.weight();

            int times = weight / maxDivisor;
            for(int i = 0; i < times; i++) { actualList.add(server); }}}}Copy the code

4. Plain hash

public class LoadBalanceCommonHash extends AbstractLoadBalanceHash {

    public LoadBalanceCommonHash(List<IServer> servers, IHash hash) {
        super(servers, hash);
    }

    @Override
    protected IServer doSelect(ILoadBalanceContext context) {
        final String hashKey = context.hashKey();

        int hashCode = Math.abs(hash.hash(hashKey));
        int index = servers.size() % hashCode;
        returnservers.get(index); }}Copy the code

5. Consistent hashing

Here we combine the consistent hashing we implemented earlier with load balancing.

public class LoadBalanceConsistentHash extends AbstractLoadBalanceHash {

    /** * consistent hash implementation *@since0.0.1 * /
    private final IConsistentHashing<IServer> consistentHashing;

    public LoadBalanceConsistentHash(List<IServer> servers, IHash hash) {
        super(servers, hash);

        this.consistentHashing = ConsistentHashingBs
                .<IServer>newInstance()
                .hash(hash)
                .nodes(servers)
                .build();
    }

    @Override
    protected IServer doSelect(ILoadBalanceContext context) {
        final String hashKey = context.hashKey();

        returnconsistentHashing.get(hashKey); }}Copy the code

Later Road Map

There is also an implementation based on system minimum pressure, minimum connection, which is not here for now.

The corresponding implementation will be added later.

Complete open source code

There are also some helper tools such as bootstrap classes.

See load-balance for the complete code