Load balancing strategy and the principle Ribbon

Load Balance Load balancing is used to solve a machine (a process) an algorithm to generate all the requests can not be solved. You can use nginx as a load balancing traffic, ribbon provide load balancing for the client, dubbo service calls in load balancing and so many places to use load balancing.

The benefits of using load balancing brings obvious:

When 1 station or cluster of multiple servers down, the remaining server is not down to ensure that services can continue to
use more machines to ensure the healthy use of the machine, not Since the peak time will lead to a sharp rise in the system cpu
load balancing there are several strategies to achieve common are:

random (random)
poll (RoundRobin)
consistent hashing (ConsistentHash)
hash (hash)
weighted (weighted)
ILoadBalance load balancer
ribbon is a provider of client service load balancing function within it provides a user interface that represents a load balancer called ILoadBalance, such as have added server operation, select the server operation, acquired all of the server list of available the list of servers, and so on. Inheritance ILoadBalance follows:





the load balancer from EurekaClient (EurekaClient implementation class DiscoveryClient) service information, according to IRule routing, and determines service availability in accordance with IPing.

The load balancer long time to get one for registration information from Eureka Client it? In BaseLoadBalancer class, BaseLoadBalancer constructor, which opens a constructor PingTask task setupPingTask () ;, code is as follows:

    BaseLoadBalancer public (String name, IRule rule, LoadBalancerStats stats,
            iPING of ping, IPingStrategy pingStrategy) {
        IF (logger.isDebugEnabled ()) {
            logger.debug ( "LoadBalancer: a initialized");
        }
        this.name = name;
        this.ping = of ping;
        this.pingStrategy = pingStrategy;
        setRule (rule);
        setupPingTask ();
        lbStats = stats;
        the init ();
    }
setupPingTask () of the specific code logic, it opens ShutdownEnabledTimer PingTask perform tasks, default is 10 pingIntervalSeconds, i.e., every 10 seconds, sending a "ping" to EurekaClient.
setupPingTask void () {
        IF (canSkipPing ()) {
            return;
        }
        IF (lbTimer = null!) {
            LbTimer.cancel ();
        }
        lbTimer new new ShutdownEnabledTimer = ( "NFLoadBalancer-PingTimer-" + name,
                to true);
        lbTimer.schedule (new new PingTask (), 0, pingIntervalSeconds * 1000);
        forceQuickPing ();
    }
PingTask source, i.e., a new object is Pinger, and performs runPinger () method.

View runPinger Pinger's () method, according to final availability pingerStrategy.pingServers (ping, allServers) to obtain the services, if the result is returned, the same as before, EurekaClient not get a list of registered destination, if different notification ServerStatusChangeListener or changeListeners happened change, update or re-pull.

The complete process is:

LoadBalancerClient (RibbonLoadBalancerClient is the implementation class) during initialization (execute methods), will pass ILoadBalance (BaseLoadBalancer is the implementation class) to obtain the service registration list to the Eureka registration center, and a send "ping", to determine the availability of services to EurekaClient every 10s If you change or service and the number of prior inconsistent availability of the service took place, from the registry update or re-pull. LoadBalancerClient With these service registration list, you can load balance based on specific IRule.



IRule routing
IRule interface represents a load balancing policy:

public interface IRule {
    public the Choose Server (Object Key);
    public void setLoadBalancer (ILoadBalancer LB);
    public ILoadBalancer getLoadBalancer ();    
}
IRule interface implementation class are the following:





wherein represents a random RandomRule strategy, RoundRobinRule represents polling policy, WeightedResponseTimeRule represents weighting strategy, BestAvailableRule represents the minimum number of requests policy and the like.

Random strategy is simple, is to select a server from the server random, RandomRule the codes are as follows:

public the Choose Server (ILoadBalancer LB, Object Key) {
    IF (LB == null) {
        null return;
    }
    Server Server = null;

    the while (Server == null) {
        IF (Thread.interrupted ()) {
            return null;
        }
        List <Server> lb.getReachableServers UPLIST = ();
        List <Server> allList = LB. getAllServers ();
        int serverCount allList.size = ();
        IF (serverCount == 0) {
            return null;
        }
        int index = rand.nextInt (serverCount); // index value obtaining random internal use jdk random class index
        Server = upList.get (index); // get the server instance

        IF (server == null) {
            to Thread.yield ();
            Continue;
        }

        IF (server.isAlive ()) {
            return (Server);
        }

        Server = null;
        to Thread.yield ();
    }
    return Server;
}
RoundRobinRule removed every polling policy indicates a server, such as a total of five servers, 1 taken 1st stage, 2nd stage to take a second, third At the third stage, and so on:

    public the Choose Server (ILoadBalancer LB, Object Key) {
        IF (LB == null) {
            log.warn ( "Load Balancer NO");
            return null;
        }

        Server Server = null;
        int COUNT = 0;
        the while (Server COUNT == null && ++ <10) {
            List <Server> reachableServers lb.getReachableServers = ();
            List <Server> allServers = lb.getAllServers ();
            int upCount = reachableServers.size();
            int serverCount = allServers.size();

            if ((upCount == 0) || (serverCount == 0)) {
                log.warn("No up servers available from load balancer: " + lb);
                return null;
            }

            int nextServerIndex = incrementAndGetModulo(serverCount);
            server = allServers.get(nextServerIndex);

            if (server == null) {
                /* Transient. */
                Thread.yield();
                continue;
            }

            if (server.isAlive() && (server.isReadyToServe())) {
                return (server);
            }

            // Next.
            server = null;
        }

        if (count >= 10) {
            log.warn("No available alive servers after 10 tries from load balancer: "
                    + lb);
        }
        return server;
    }

    /**
     * Inspired by the implementation of {@link AtomicInteger#incrementAndGet()}.
     *
     * @param modulo The modulo to bound the value of the counter.
     * @return The next value.
     */
    private int incrementAndGetModulo(int modulo) {
        for (;;) {
            int current = nextServerCyclicCounter.get();
            Next = int (Current +. 1) modulo%;
            IF (nextServerCyclicCounter.compareAndSet (Current, Next))
                return Next;
        }
    }
WeightedResponseTimeRule inherited RoundRobinRule, not beginning with the weight list, polling using the parent class, there is a default update every 30 seconds the weight list timing task, the scheduled task will be updated to re-listing weight based on the response time instance, the Choose a method to do that, the random number double with a (0,1) is multiplied by the maximum weight to give randomWeight, then traverse the weight list, find the first instance of a larger than randomWeight subscript, and then returns that instance, the code slightly.

BestAvailableRule Policy Server for selecting the least amount of concurrent requests:

public the Choose Server (Object Key) {
    IF (loadBalancerStats == null) {
        return super.choose (Key);
    }
    List <Server> ServerList = getLoadBalancer () getAllServers (). ; // get a list of all servers
    int minimalConcurrentConnections = Integer.MAX_VALUE;
    currentTime = System.currentTimeMillis Long ();
    Server Chosen = null;
    for (Server Server: ServerList) {// iterate through each server
        ServerStats serverStats = loadBalancerStats.getSingleServerStat (server); // obtain the status of each server
        if (serverStats!. isCircuitBreakerTripped (currentTime)) {// if the circuit breaker is not triggered continue
            int concurrentConnections = serverStats.getActiveRequestsCount (currentTime); // get the current number of requests to the server
            between requests if (concurrentConnections <minimalConcurrentConnections) {// each server comparison number, and select the minimum number of server requests and placed Chosen variable
                minimalConcurrentConnections = concurrentConnections;
                Chosen = server;
            }
        }
    }
    if (chosen == null) {// If the option is not, call the parent class ClientConfigEnabledRoundRobinRule choose, i.e. RoundRobinRule polling mode used for load balancing        
        return super.choose (Key);
    } the else {
        return Chosen;
    }
}
Ribbon load-balancing strategy available is quite simple, just following portions:

1, RestTemplate create instances of the load balancing function has

@Bean
@LoadBalanced
RestTemplate RestTemplate () {
    return new new RestTemplate ();
}
using RestTemplate operation time for rest, will automatically load balancing strategy, it will join LoadBalancerInterceptor inside the interceptor in RestTemplate, the role of this interceptor is to use load balancing.
Will use the default polling policy, other strategies employed if desired, specify IRule achieved, such as:

@Bean
public IRule ribbonRule () {
    return new new BestAvailableRule ();
}
This approach is also valid for Feign.

We can also refer ribbon, wrote a load balancing implementation class.

Can be obtained by the following method of load balancing policy ultimately chose which service instance:

        @Autowired
        LoadBalancerClient loadBalancerClient; 
        
        // Load balancing test ultimately select which instance of
        public String getChoosedService () {
            ServiceInstance ServiceInstance = loadBalancerClient.choose ( "USERINFO-the SERVICE");
            the StringBuilder the StringBuilder new new = SB ();
            sb.append ( "Host:") .append (serviceInstance.getHost ()) the append ( ",");.
            sb.append ( "Port:") .append (serviceInstance.getPort () ) .append ( ",");
            sb.append ( "URI:") .append (serviceInstance.getUri ());
            return sb.toString ();
        }

description link:https://blog.csdn.net/wudiyong22/article/details/80829808

Published 795 original articles · won praise 3 · Views 110,000 +

Guess you like

Origin blog.csdn.net/u010395024/article/details/105043251