All Downloads are FREE. Search and download functionalities are using the official Maven repository.

netflix.ocelli.loadbalancer.RandomWeightedLoadBalancer Maven / Gradle / Ivy

There is a newer version: 0.1.0-rc.2
Show newest version
package netflix.ocelli.loadbalancer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;

import netflix.ocelli.LoadBalancer;
import netflix.ocelli.loadbalancer.weighting.ClientsAndWeights;
import netflix.ocelli.loadbalancer.weighting.WeightingStrategy;
import rx.Subscriber;

/**
 * Select the next element using a random number.  
 * 
 * The weights are sorted such as that each cell in the array represents the
 * sum of the previous weights plus its weight.  This structure makes it 
 * possible to do a simple binary search using a random number from 0 to 
 * total weights.
 * 
 * Runtime complexity is O(log N)
 * 
 * @author elandau
 *
 */
public class RandomWeightedLoadBalancer extends LoadBalancer {
    public static  RandomWeightedLoadBalancer create(final WeightingStrategy strategy) {
        return new RandomWeightedLoadBalancer(strategy);
    }

    private final AtomicReference> clients;
    
    public RandomWeightedLoadBalancer(final WeightingStrategy strategy) {
        this(strategy, new AtomicReference>(new ArrayList()));
    }

    RandomWeightedLoadBalancer(final WeightingStrategy strategy, final AtomicReference> clients) {
        super(new OnSubscribe() {
            
            private final Random rand = new Random();
            
            @Override
            public void call(final Subscriber s) {
                List local = clients.get();

                final ClientsAndWeights caw = strategy.call(local);
                if (!caw.isEmpty()) {
                    int total = caw.getTotalWeights();
                    if (total == 0) {
                        s.onNext(caw.getClient(rand.nextInt(caw.size())));
                        s.onCompleted();
                    }
                    else {
                        int pos = Collections.binarySearch(caw.getWeights(), rand.nextInt(total));
                        if (pos >= 0) {
                            pos = pos+1;
                        }
                        else {
                            pos = -(pos) - 1;
                        }

                        s.onNext(caw.getClient(pos));
                        s.onCompleted();
                    }
                }
                else {
                    s.onError(new NoSuchElementException("No servers available in the load balancer"));
                }
            }
        });
        
        this.clients = clients;
    }
    
    @Override
    public void call(List t) {
        this.clients.set(t);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy