RPC客户端负载均衡

0x00 负载均衡的插入点

一般是客户端或调用方进行负载均衡的处理。

0x01 常见的负载均衡策略

LocalFirst-本地优先

获取所有的本地服务提供者,按照一定顺序,取得被调用次数最小的服务提供者。

public class LocalFirstLoadBalance {


    public static void main(String[] args) {
        LocalFirstLoadBalance balance = new LocalFirstLoadBalance();
        for (int i = 0; i < 10; i++) {
            Refer refer = balance.getRefer();
            System.out.println(refer);
            refer.incrActiveCount("");
        }
    }

    public Refer getRefer() {
        List<Refer> refers = getLocalRefers();
        Refer refer = null;
        for (int i = 0; i < refers.size(); i++) {
            int index = i % refers.size();
            Refer temp = refers.get(index);
            if (!ReferUtils.isReferAvailable(temp)) {
                continue;
            }

            if (refer == null) {
                refer = temp;
            } else {
                if (compare(refer, temp) > 0) {
                    refer = temp;
                }
            }

        }
        return refer;
    }

    private int compare(Refer referer1, Refer referer2) {
        return referer1.activeRefererCount() - referer2.activeRefererCount();
    }

    private List<Refer> getLocalRefers() {
        List<Refer> allRefers = ReferUtils.getAllRefers();
        List<Refer> collect = allRefers.stream().filter(ReferUtils::isLocalRefer).collect(Collectors.toList());
        return collect;
    }

}

RandomLocal-本地随机

获取所有的本地服务提供者,随机获取其中一个服务提供者。

public class RandomLocalBalance {

    private List<Refer> refers;

    public RandomLocalBalance() {
        refers = getRefers();
    }

    public static void main(String[] args) {
        RandomLocalBalance balance = new RandomLocalBalance();
        for (int i = 0; i < 100; i++) {
            Refer refer = balance.getRefer();
            System.out.println(refer);
            refer.incrActiveCount("");
        }
    }

    public Refer getRefer() {
        List<Refer> refers = getRefers();
        int idx = (int) (ThreadLocalRandom.current().nextDouble() * refers.size());
        for (int i = 0; i < refers.size(); i++) {
            int index = (idx + i) % refers.size();
            Refer refer = refers.get(index);
            if (ReferUtils.isReferAvailable(refer)) {
                return refer;
            }
        }
        return null;
    }

    private List<Refer> getRefers() {
        List<Refer> allRefers = ReferUtils.getAllRefers();
        List<Refer> collect = allRefers.stream().filter(ReferUtils::isLocalRefer).collect(Collectors.toList());
        return collect;
    }
}

RoundRobin-轮流

获取所有的服务提供者,按顺序依次调用。

public class RoundRobinLoadBalance {

    private AtomicInteger idx = new AtomicInteger(0);


    public static void main(String[] args) {

        RoundRobinLoadBalance balance = new RoundRobinLoadBalance();
        for (int i = 0; i < 10; i++) {
            Refer refer = balance.getRefer();
            System.out.println(refer);
            refer.incrActiveCount("");
        }
    }

    public Refer getRefer() {
        List<Refer> refers = getRefers();
        int nextIdx = getNextIdx();
        for (int i = 0; i < refers.size(); i++) {
            int index = (nextIdx + i) % refers.size();
            System.out.printf("nextIdx:%d i:%d result:%d\n", nextIdx, i, index);
            Refer ref = refers.get(index);
            if (ReferUtils.isReferAvailable(ref)) {
                return ref;
            }
        }
        return null;
    }


    private List<Refer> getRefers() {
        return ReferUtils.getAllRefers();
    }

    private int getNextIdx() {
        return idx.getAndIncrement();
    }
}

ConsistentHash-一致性哈希

将所有的服务提供者随机分布到更大的列表中,然后根据请求的hash值,获取对应的服务提供者。这样保证同样的请求分布到相同的服务提供者上,同时由于使用了更大的列表,避免了请求集中在同一服务器上,使得请求分布更加均衡。

public class ConsistentHashLoadBalance {

    private List<Refer> refers;

    public ConsistentHashLoadBalance() {
        refers = getRefers();
    }

    public static void main(String[] args) {
        ConsistentHashLoadBalance balance = new ConsistentHashLoadBalance();
        for (int i = 0; i < 100; i++) {
            Refer refer = balance.getRefer(String.valueOf(i % 20));
            System.out.println(refer);
            refer.incrActiveCount("");
        }

    }

    public Refer getRefer(String request) {
        int hash = getHash(request);
        for (int i = 0; i < refers.size(); i++) {
            int index = (hash + i) % refers.size();
            System.out.println(index);
            Refer refer = refers.get(index);
            if (ReferUtils.isReferAvailable(refer)) {
                return refer;
            }
        }
        return null;
    }

    private List<Refer> getRefers() {
        List<Refer> allRefers = ReferUtils.getAllRefers();
        List<Refer> copyRefers = new ArrayList<>(allRefers);
        List<Refer> tempRefers = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            Collections.shuffle(copyRefers);
            for (Refer ref : copyRefers) {
                tempRefers.add(ref);
            }
        }
        return tempRefers;
    }

    private int getHash(String request) {
        return request.hashCode();
    }
}

ActiveWeight-活跃权重

获取所有的服务提供者,根据各个服务提供者的活跃权重,获取响应的服务提供者。下例中,取得服务者提供的活跃调用次数小。

public class ActiveWeightLoadBalance {

    public static void main(String[] args) {

        ActiveWeightLoadBalance balance = new ActiveWeightLoadBalance();
        for (int i = 0; i < 10; i++) {
            Refer refer = balance.getRefer();
            System.out.println(refer);
        }
    }

    public Refer getRefer() {
        List<Refer> refers = getRefers();
        Refer refer = null;
        for (int i = 0; i < refers.size(); i++) {
            int index = i % refers.size();
            Refer temp = refers.get(index);
            if (!ReferUtils.isReferAvailable(temp)) {
                continue;
            }

            if (refer == null) {
                refer = temp;
            } else {
                if (compare(refer, temp) > 0) {
                    refer = temp;
                }
            }

        }
        return refer;
    }

    private int compare(Refer referer1, Refer referer2) {
        return referer1.activeRefererCount() - referer2.activeRefererCount();
    }

    private List<Refer> getRefers() {
        List<Refer> allRefers = ReferUtils.getAllRefers();
        return allRefers;
    }
}

标签: Java, blog, rpc

添加新评论