【分布式】load balance 04-java 从零手写实现负载均衡

负载均衡系列专题

01-负载均衡基础知识

02-一致性 hash 原理

03-一致性哈希算法 java 实现

04-负载均衡算法 java 实现

本节我们来看一下如何实现一负载均衡框架。

源码

核心接口定义

public interface ILoadBalance {

    /**
     * 选择下一个节点
     *
     * 返回下标
     * @param context 上下文
     * @return 结果
     * @since 0.0.1
     */
    IServer select(final ILoadBalanceContext context);

}

1. 随机策略

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. 轮训

public class LoadBalanceRoundRobbin extends AbstractLoadBalance {

    /**
     * 位移指针
     * @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. 有权重的轮训

这个需要对数据进行初始化处理,计算数组的最大公约数。

public class LoadBalanceWeightRoundRobbin extends AbstractLoadBalance {

    /**
     * 位移指针
     * @since 0.0.1
     */
    private final AtomicLong indexHolder = new AtomicLong();

    /**
     * 处理后的列表
     * @since 0.0.1
     */
    private final List<IServer> actualList = new ArrayList<>();

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

        // 初始化真实列表
        this.init(servers);
    }

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

        // 基于真实的列表构建
        int actual = (int) (index % actualList.size());
        return actualList.get(actual);
    }

    /**
     * 初始化
     * @param serverList 服务列表
     * @since 0.0.1
     */
    private void init(final List<IServer> serverList) {
        //1. 过滤掉权重为 0 的机器
        List<IServer> notZeroServers = CollectionUtil.filterList(serverList, new IFilter<IServer>() {
            @Override
            public boolean filter(IServer iServer) {
                return iServer.weight() <= 0;
            }
        });

        //2. 获取权重列表
        List<Integer> weightList = CollectionUtil.toList(notZeroServers, new IHandler<IServer, Integer>() {
            @Override
            public Integer handle(IServer iServer) {
                return iServer.weight();
            }
        });

        //3. 获取最大的权重
        int maxDivisor = MathUtil.ngcd(weightList);

        //4. 重新计算构建基于权重的列表
        for(IServer server : notZeroServers) {
            int weight = server.weight();

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

}

4. 普通哈希

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. 一致性哈希

这里将我们前面实现的一致性哈希,与负载均衡结合。

public class LoadBalanceConsistentHash extends AbstractLoadBalanceHash {

    /**
     * 一致性 hash 实现
     * @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);
    }

}

后期 Road-Map

还有基于系统最小压力,最小连接的实现,暂时没有放在这里。

后续将加入对应的实现。

完整开源代码

其他还有一些引导类等辅助工具。

完整代码参见 load-balance

【分布式】load balance 04-java 从零手写实现负载均衡

原文 

https://segmentfault.com/a/1190000022981126

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 【分布式】load balance 04-java 从零手写实现负载均衡

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址