class WeightRoundRobinLoadBalancer extends AbstractLoadBalancer {

    @Override
    public ProviderInfo doSelect(SofaRequest request, List<ProviderInfo> providerInfos) {
        String key = getServiceKey(request); // 每个方法级自己轮询，互不影响
        int length = providerInfos.size(); // 总个数
        int maxWeight = 0; // 最大权重
        int minWeight = Integer.MAX_VALUE; // 最小权重

        final LinkedHashMap<ProviderInfo, IntegerWrapper> invokerToWeightMap = new LinkedHashMap<ProviderInfo, IntegerWrapper>();
        int weightSum = 0;
        for (ProviderInfo providerInfo : providerInfos) {
            int weight = getWeight(providerInfo);
            maxWeight = Math.max(maxWeight, weight); // 累计最大权重
            minWeight = Math.min(minWeight, weight); // 累计最小权重
            if (weight > 0) {
                invokerToWeightMap.put(providerInfo, new IntegerWrapper(weight));
                weightSum += weight;
            }
        }
        PositiveAtomicCounter sequence = sequences.get(key);
        if (sequence == null) {
            sequences.putIfAbsent(key, new PositiveAtomicCounter());
            sequence = sequences.get(key);
        }
        int currentSequence = sequence.getAndIncrement();
        if (maxWeight > 0 && minWeight < maxWeight) { // 权重不一样
            int mod = currentSequence % weightSum;
            for (int i = 0; i < maxWeight; i++) {
                for (Map.Entry<ProviderInfo, IntegerWrapper> each : invokerToWeightMap.entrySet()) {
                    final ProviderInfo k = each.getKey();
                    final IntegerWrapper v = each.getValue();
                    if (mod == 0 && v.getValue() > 0) {
                        return k;
                    }
                    if (v.getValue() > 0) {
                        v.decrement();
                        mod--;
                    }
                }
            }
        }
        return providerInfos.get(currentSequence % length);
        /*
        for (int i = 0; i < length; i++) {
            int weight = getWeight(providerInfos.get(i));
            maxWeight = Math.max(maxWeight, weight); // 累计最大权重
            minWeight = Math.min(minWeight, weight); // 累计最小权重
        }
        if (maxWeight > 0 && minWeight < maxWeight) { // 权重不一样,不再按照之前轮询顺序，
            PositiveAtomicCounter weightSequence = weightSequences.get(key);
            if (weightSequence == null) {
                weightSequences.putIfAbsent(key, new PositiveAtomicCounter());
                weightSequence = weightSequences.get(key);
            }
            int currentWeight = weightSequence.getAndIncrement() % maxWeight;
            List<ProviderInfo> weightInvokers = new ArrayList<ProviderInfo>();
            for (ProviderInfo invoker : providerInfos) { // 筛选权重大于当前权重基数的provider,保证权重大的服务哪怕是轮询，被调用的机会也是最多的
                if (getWeight(invoker) > currentWeight) {
                    weightInvokers.add(invoker);
                }
            }
            int weightLength = weightInvokers.size();
            if (weightLength == 1) {
                return weightInvokers.get(0);
            } else if (weightLength > 1) {
                providerInfos = weightInvokers;
                length = providerInfos.size();
            }
        }
        PositiveAtomicCounter sequence = sequences.get(key);
        if (sequence == null) {
            sequences.putIfAbsent(key, new PositiveAtomicCounter());
            sequence = sequences.get(key);
        }
        return providerInfos.get(sequence.getAndIncrement() % length);*/
    }

    public  WeightRoundRobinLoadBalancer(ConsumerBootstrap consumerBootstrap);

}