[distributed] load balance 04 Java realizes load balance from zero handwriting

Time:2021-11-28

Load balancing series topics

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, let’s look at how to implement a load balancing framework.

Source code

Core interface definition

public interface ILoadBalance {

    /**
     *Select next node
     *
     *Return subscript
     *@ param context context
     *@ return result
     * @since 0.0.1
     */
    IServer select(final ILoadBalanceContext context);

}

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());
        return servers.get(nextIndex);
    }

}

2. Rotation training

public class LoadBalanceRoundRobbin extends AbstractLoadBalance {

    /**
     *Displacement pointer
     * @since 0.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());
        return servers.get(actual);
    }

}

3. Weighted rotation training

This needs to initialize the data and calculate the maximum common divisor of the array.

public class LoadBalanceWeightRoundRobbin extends AbstractLoadBalance {

    /**
     *Displacement pointer
     * @since 0.0.1
     */
    private final AtomicLong indexHolder = new AtomicLong();

    /**
     *Processed list
     * @since 0.0.1
     */
    private final List<IServer> actualList = new ArrayList<>();

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

        //Initialize 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);
    }

    /**
     *Initialization
     *@ param serverlist service list
     * @since 0.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 weight list
        List<Integer> weightList = CollectionUtil.toList(notZeroServers, new IHandler<IServer, Integer>() {
            @Override
            public Integer handle(IServer iServer) {
                return iServer.weight();
            }
        });

        //3. Get the maximum weight
        int maxDivisor = MathUtil.ngcd(weightList);

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

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

}

4. Ordinary 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;
        return servers.get(index);
    }

}

5. Consistency hash

Here we combine the consistency hash we implemented earlier with load balancing.

public class LoadBalanceConsistentHash extends AbstractLoadBalanceHash {

    /**
     *Consistent hash implementation
     * @since 0.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();

        return consistentHashing.get(hashKey);
    }

}

Later road map

There is also the realization of minimum connection based on the minimum pressure of the system, which is not put here for the time being.

The corresponding implementation will be added later.

Complete open source code

There are other auxiliary tools such as boot classes.

See for complete codeload-balance

[distributed] load balance 04 Java realizes load balance from zero handwriting