This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

AbstractLoadBalancer for load balancer

AbstractLoadBalancer

AbstractLoadBalancer is an abstract implementation of the ILoadBalancer interface

public abstract class AbstractLoadBalancer implements ILoadBalancer {
    
    public enum ServerGroup{
        ALL,
        STATUS_UP,
        STATUS_NOT_UP        
    }
        
    /**
     * delegate to {@link #chooseServer(Object)} with parameter null.
     */
    public Server chooseServer(a) {
       return chooseServer(null);
    }

    
    /**
     * List of servers that this Loadbalancer knows about
     * 
     * @param serverGroup Servers grouped by status, e.g., {@link ServerGroup#STATUS_UP}
     */
    public abstract List<Server> getServerList(ServerGroup serverGroup);
    
    /** * Obtain LoadBalancer related Statistics */
    public abstract LoadBalancerStats getLoadBalancerStats(a);    
}
Copy the code

Define the enumerated class ServerGroup

  • ALL Indicates ALL service instances
  • STATUS_UP: indicates a normal service instance
  • STATUS_NOT_UP: stops the service instance

Abstract methods

GetServerList (ServerGroup ServerGroup) : defines a list of different service instances to get based on the group type

getLoadBalancerStats(); Defines a method to get a LoadBalancerStats object that is used to store the current properties and statistics of each service instance in the load balancer.

BaseLoadBalancer

BaseLoadBalancer is the basic implementation class for the Ribbon load balancer

  • Define and maintain lists of two storage service instance Server objects, one for storing all service instances and one for storing normal services

    @Monitor(name = PREFIX + "AllServerList", type = DataSourceType.INFORMATIONAL)
    protected volatile List<Server> allServerList = Collections
            .synchronizedList(new ArrayList<Server>());
    @Monitor(name = PREFIX + "UpServerList", type = DataSourceType.INFORMATIONAL)
    protected volatile List<Server> upServerList = Collections
            .synchronizedList(new ArrayList<Server>());
    Copy the code
  • Defines the LoadBalancerStats object that was previously used to store attributes and statistics for each service instance of the load balancer.

  • BaseLoadBalancer defines an IPing object that checks whether a service instance is in service, which defaults to null in BaseLoadBalancer and needs to be injected at construction time

  • Defines the execution policy object IPingStrategy that examines the operation of a service instance, using static inner classes defined in this class by default

 private static class SerialPingStrategy implements IPingStrategy {
 
     @Override
     public boolean[] pingServers(IPing ping, Server[] servers) {
         int numCandidates = servers.length;
         boolean[] results = new boolean[numCandidates];
 
         if (logger.isDebugEnabled()) {
             logger.debug("LoadBalancer: PingTask executing ["
                          + numCandidates + "] servers configured");
         }
 
         for (int i = 0; i < numCandidates; i++) {
             results[i] = false; /* Default answer is DEAD. */
             try {
                 // NOTE: IFF we were doing a real ping
                 // assuming we had a large set of servers (say 15)
                 // the logic below will run them serially
                 // hence taking 15 times the amount of time it takes
                 // to ping each server
                 // A better method would be to put this in an executor
                 // pool
                 // But, at the time of this writing, we dont REALLY
                 // use a Real Ping (its mostly in memory eureka call)
                 // hence we can afford to simplify this design and run
                 // this
                 // serially
                 if(ping ! =null) { results[i] = ping.isAlive(servers[i]); }}catch (Throwable t) {
                 logger.error("Exception while pinging Server:"+ servers[i], t); }}returnresults; }}Copy the code
  • The load balancer actually delegates the service instance selection task to the Choose method of the IRule instance to implement. By default, RoundRobinRule is initialized as the IRule implementation object. RoundRobinRule implements the basic linear load balancing rules.
public Server chooseServer(Object key) {
    if (counter == null) {
        counter = createCounter();
    }
    counter.increment();
    if (rule == null) {
        return null;
    } else {
        try {
            return rule.choose(key);
        } catch (Throwable t) {
            return null; }}}Copy the code

BaseLoadBalancer: In the BaseLoadBalancer default constructor, a BaseLoadBalancer task is directly started to periodically check whether the Server is healthy. The default execution interval is 10 seconds

Implement ILoadBalancer interface:

ChooseServer method

AddServers method:

public void addServers(List<Server> newServers) {
    if(newServers ! =null && newServers.size() > 0) {
        try {
            ArrayList<Server> newList = new ArrayList<Server>();
            newList.addAll(allServerList);
            newList.addAll(newServers);
            setServersList(newList);
        } catch (Exception e) {
            logger.error("Exception while adding Servers", e); }}}Copy the code

GetReachableServers method: Gets a list of available service instances

public List<Server> getReachableServers(a) {
    return Collections.unmodifiableList(upServerList);
}
Copy the code

Maintain a separate list of instances of normal services and return directly

GetAllServers method: Gets a list of all service instances

@Override
public List<Server> getAllServers() {
    return Collections.unmodifiableList(allServerList);
}
Copy the code