A, introducing

In this section, we will analyze the source code of the load balancer component. After this article, we will combine the previous RestTemplate with the content of this chapter, so as to get the principle of RestTemplate integrating Eureka with the Ribbon to achieve load balancingCopy the code

Ii. Analysis of ILoadBalancer inheritance system and interface method

1. ILoadBalancer interface analysis

LoadBalancer in the Ribbon implements a complete set of load balancing functions, using a List to store all the services, using the IRule interface to define the function of retrieving services from the service List with certain rules. The IPing interface has also been added to determine whether the service is alive or not.public interface ILoadBalancer {
	public void addServers(List<Server> newServers);
	public Server chooseServer(Object key);
	public void markServerDown(Server server);
	public List<Server> getServerList(boolean availableOnly);
    public List<Server> getReachableServers(a);
	public List<Server> getAllServers(a); } addServers is used to add services to a List of servers by default. The Server class is a simple definition of a service, such as host, port:public class Server {
    private int port;
    private String scheme;
    privateString host; } chooseServer is a way to select a Server from a List and return it. The key is a hint that filters servers. Key can be a serviceId, that is, select a suitable Server from a category of services. For example, the serviceId is CartService. In the default implementation of ILoadBalancer, getServerList is used to get the list of services we mentioned above, There are two lists to hold the List of services, the first to hold all the service lists, the second to hold the List of available services (not offline), and the parameter availableOnly in the getServerList method is used to specify which service List to get, iftrueGets a list of available services, or a list of all services saved, but this method has been identified as@DeprecatedDeprecated, replaced by the latter two methods getReachableServers and getAllServersCopy the code

2. AbstractLoadBalancer method and function analysis

public abstract class AbstractLoadBalancer implements ILoadBalancer {
    public enum ServerGroup{
        ALL,
        STATUS_UP,
        STATUS_NOT_UP        
    }
        
    public Server chooseServer(a) { return chooseServer(null); }
    public abstract List<Server> getServerList(ServerGroup serverGroup);
    public abstract LoadBalancerStats getLoadBalancerStats(a); } In the ILoadBalancer interface, there is a service list that does not provide an interface to get a list of services that are not available ----, so in AbstractLoadBalancer, ServerGroup.ALL means to obtain a list of ALL services, equivalent to the getAllServers method in ILoadBalancer, ServerGroup.STATUS_UP means to obtain a list of available services, Servergroup.status_not_up = servergroup.status_not_up = servergroup.status_not_up The getServerList method is used to obtain a list of different types of services from ServerGroup. GetLoadBalancerStats is used to obtain the status of the load balancer. A class that acts as a repository of operational characteristics and statistics for each node/server in LaodBalancer. This information can be used to simply observe and resolve the runtime behavior of the load balancer, or more importantly, it is the basis for determining the load balancing strategyCopy the code

3, BaseLoadBalancer source analysis

The default implementation of the load balancer, in the face of the load balancer should have some functions are implemented, first let's look at the definition of the properties:public class BaseLoadBalancer extends AbstractLoadBalancer {
    private final static IRule DEFAULT_RULE = new RoundRobinRule();
    private final static SerialPingStrategy DEFAULT_PING_STRATEGY
                                                         = new SerialPingStrategy();

    protected IRule rule = DEFAULT_RULE;
    protected IPingStrategy pingStrategy = DEFAULT_PING_STRATEGY;
    protected IPing ping;

    protected volatile List<Server> allServerList = Collections
            .synchronizedList(new ArrayList<Server>());

    protected volatile List<Server> upServerList = Collections
            .synchronizedList(new ArrayList<Server>());

    protected Timer lbTimer = null;

    protected ReadWriteLock allServerLock = new ReentrantReadWriteLock();
    protected ReadWriteLock upServerLock = newReentrantReadWriteLock(); } DEFAULT_RULE is the default load balancing policy implementation for filtering services, DEFAULT_PING_STRATEGY is the default Ping policy, Used to determine whether the service is alive or not (in Eureka this is the status of InstanceInfo, if you are familiar with the Eureka source code, InstanceInfo is the object representation of services in Eureka.) allServerList and upServerList are the lists of all services and the lists of surviving services analyzed in the previous section. LbTimer is a timer. AllServerLock is a read/write lock, which is used to ensure the thread security of the read/write operations on the allServerList. The upServerLock is similar to the read-write lock that is used to ensure thread-safety for upServerList reads and writespublic class BaseLoadBalancer extends AbstractLoadBalancer {
    public List<Server> getServerList(ServerGroup serverGroup) {
        switch (serverGroup) {
        case ALL:
            return allServerList;
        case STATUS_UP:
            return upServerList;
        case STATUS_NOT_UP:
            ArrayList<Server> notAvailableServers = new ArrayList<Server>(
                    allServerList);
            ArrayList<Server> upServers = new ArrayList<Server>(upServerList);
            notAvailableServers.removeAll(upServers);
            return notAvailableServers;
        }
        return new ArrayList<Server>();
    }

    public Server chooseServer(Object key) {
        if (counter == null) {
            counter = createCounter();
        }
        counter.increment();
        if (rule == null) {
            return null;
        } else {
            returnrule.choose(key); }}} addServers is a simple way to update allServerList and upServerList to provide thread-safe control for multithreading. The ServerGroup is used to determine the type of service list to be obtained. The ServerGroup is used to determine the type of service list to be obtained. IRule's abstract implementation holds a reference to ILoadBalancer, which is a reference to ILoadBalancer. So you can get a list of all the servicesCopy the code

4. Import DiscoveryEnabledServer

public class DiscoveryEnabledServer extends Server{
    private final InstanceInfo instanceInfo;

    // Abbreviated version
    public DiscoveryEnabledServer(final InstanceInfo instanceInfo,
                                             boolean useSecurePort, boolean useIpAddr) {
        super(useIpAddr ? instanceInfo.getIPAddr() : instanceInfo.getHostName(), instanceInfo.getPort()); }} In the above analysis, all the Server objects are stored in the service list. When Eureka integrates the Ribbon, it is easy to connect the Eureka service to the Server by inherits the Server object. DiscoveryEnabledServer uses a built-in InstanceInfo object that holds service instances in Eureka. This InstanceInfo object is used to set the host and port information in the Server. DiscoveryEnabledServer and DomainExtractingServer are subclasses. The function of the DomainExtractingServer extension is to extract domain data in host and save it, so it is called Domain fully Server. DomainExtractingServer was created when Eureka integrated the RibbonCopy the code

5, DynamicServerListLoadBalancer attribute analysis

BaseLoadBalancer to the function of load balancing in the realization of basic, while DynamicServerListLoadBalancer provides dynamic refresh list of service function, such as every once in a while from Eureka pull the latest data and update the list, Let's start by talking about some of its properties:public class DynamicServerListLoadBalancer<T extends Server> extends BaseLoadBalancer {
    volatile ServerList<T> serverListImpl;
    volatile ServerListFilter<T> filter;
    protected final ServerListUpdater.UpdateAction updateAction 
                        = new ServerListUpdater.UpdateAction() {
                            @Override
                            public void doUpdate(a) { updateListOfServers(); }};protected volatileServerListUpdater serverListUpdater; } updateAction is a functional interface that provides a doUpdate method that, when called, starts updating the list of services and internally performs this function through the updateListOfServers method. If we want to see how to update the list of services dynamically, we'll look at the implementation of updateListOfServers, and then we'll look at serverListUpdater, The default implementation of Ribbon is PollingServerListUpdater Eureka consolidation, use a timer to cycle call updateAction doUpdate methods, in PollingServerListUpdater is as follows:public class PollingServerListUpdater implements ServerListUpdater {
    private static long LISTOFSERVERS_CACHE_UPDATE_DELAY = 1000; // msecs;
    private static int LISTOFSERVERS_CACHE_REPEAT_INTERVAL = 30 * 1000; // msecs;
   
    @Override
    public synchronized void start(final UpdateAction updateAction) {
        final Runnable wrapperRunnable = new Runnable() {
            @Override
            public void run(a) { updateAction.doUpdate(); }}; scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay( wrapperRunnable, initialDelayMs, refreshIntervalMs, TimeUnit.MILLISECONDS ); }} wrapperRunnable's run function is executed every refreshIntervalMs, and updateAction.doupDate () is executed inside the run function1Seconds, and then every other time30ServerListFilter is executed once every second. This filter is used to update the ServerList, indicating which servers need to be filtered. Interested students can learn about the implementation of this filter separately. Let's start by analyzing the implementation of updateListOfServers. How do we dynamically update the list of servicespublic class DynamicServerListLoadBalancer<T extends Server> extends BaseLoadBalancer {
    volatile ServerList<T> serverListImpl;

    public void updateListOfServers(a) {
        List<T> servers = new ArrayList<T>();
        if(serverListImpl ! =null) {
            servers = serverListImpl.getUpdatedListOfServers();

            if(filter ! =null) { servers = filter.getFilteredListOfServers(servers); } } updateAllServerList(servers); .}} by serverListImpl getUpdatedListOfServers method to get the latest service list, if the filter is not null, use the filter for filtering, Finally, we call the updateAllServerList method to update the latest list of services to allServerList and upServerList in BaseLoadBalancer, so the class that really gets the latest list of services is ServerList. How does ServerList get the latest list of servicesCopy the code

ServerList Obtains the latest service list

public class DiscoveryEnabledNIWSServerList 
                            extends AbstractServerList<DiscoveryEnabledServer>{
    private final Provider<EurekaClient> eurekaClientProvider;
    public List<DiscoveryEnabledServer> getUpdatedListOfServers(a){
        returnobtainServersViaDiscovery(); }} First take a look at the generic DiscoveryEnabledServer. In section 4 above, we analyzed DiscoveryEnabledServer. It associates the Eureka service with the Server object by inheriting from the Server and storing the InstanceInfo object internally. Now let's look at the properties. There's a eurekaClientProvider. Acquiring EurekaClient can get the latest list of services, in the previous section, we know through getUpdatedListOfServers to retrieve the latest list of services, and truly is done through obtainServersViaDiscovery methodprivate List<DiscoveryEnabledServer> obtainServersViaDiscovery(a) {
    List<DiscoveryEnabledServer> serverList = new ArrayList<DiscoveryEnabledServer>();

    EurekaClient eurekaClient = eurekaClientProvider.get();
    if(vipAddresses! =null) {for (String vipAddress : vipAddresses.split(",")) {
            List<InstanceInfo> listOfInstanceInfo = 
                eurekaClient.getInstancesByVipAddress(vipAddress, isSecure, targetRegion);
            for (InstanceInfo ii : listOfInstanceInfo) {
                if(ii.getStatus().equals(InstanceStatus.UP)) { DiscoveryEnabledServer des = createServer(ii, isSecure, shouldUseIpAddr); serverList.add(des); }}}}returnserverList; } Address: vipAddresses are briefly addressed in my Eureka post, for example, in my EurekaServer100As a EurekaClient, I only expect to pull shopping cart and order services, so that EurekaClient will only pull specific types of services from EurekaServer by specifying vipAddresses for these two services in the code above. EurekaClient is used to get the latest list of services for the specified type of service, so only vipAddresses are updated here. This is because our different services have different LoadBalancer. For example, the shopping cart service has its own LoadBalancer, and the separation of LoadBalancer for each service is done by SpringClientFactory in the previous article. Therefore, when dynamically refreshing the service list in LoadBalancer, only the service list of the current type is dynamically refreshed. After obtaining the latest service list, encapsulate it as DiscoveryEnabledServer and return itCopy the code

Third, summary

LoadBalancer LoadBalancer LoadBalancer LoadBalancer LoadBalancer1The default implementation of BaseLoadBalancer defines a basic load balancer function, such as a List of storage services, an IPing interface to determine whether the service is in stock, and Ping policies. AbstractLoadBalancer (ILoadBalancer, AbstractLoadBalancer, AbstractLoadBalancer);2> in order to be able to dynamically update the list of services, the introduction of the DynamicServerListLoadBalancer, in the class by ServerListUpdater. UpdateAction to complete service list updates, In its doUpdate method by calling DynamicServerListLoadBalancer updateListOfServers method to accomplish dynamic update the service list, By calling the interior ServerList getUpdatedListOfServers method of ServerList subclass DiscoveryEnabledNIWSServerList namely is the realization of the integration of Eureka, An internal EurekaClient is placed, which implements the getUpdatedListOfServers method to get the latest list of services.3> extension: Eureka integration Ribbon, create LoadBalancer ZoneAwareLoadBalancer, its is a subclass of DynamicServerListLoadBalancer, increased Zone area this concept, Interested can go to see the Zone in Eureka, create ServerList DomainExtractingServerList, its internal saved the DiscoveryEnabledNIWSServerList we analyzed above, On the basis of DiscoveryEnabledNIWSServerList increased the function of the ZoneCopy the code