Ribbon ILoadBalancer 负载均衡源码分析

上一篇看到,在执行LoadBalancerInterceptor.intercept拦截器方法的时候,会调用LoadBalancerClient.execute方法,

即RibbonLoadBalancerClient.execute方法

public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
    ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
    Server server = this.getServer(loadBalancer, hint);
    if(server == null) {
        throw new IllegalStateException("No instances available for " + serviceId);
    } else {
        RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
        return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);
    }
}

根据serviceId(服务名称)获得ILoadBalancer 实例(每个服务名称都会对应一个ILoadBalancer 实例),然后通过ILoadBalancer 的负载均衡策略选择合适的服务器。那么ILoadBalancer 是如何初始化的,如何找到对应服务的ILoadBalancer ?

public <C> C getInstance(String name, Class<C> type) {
    Object instance = super.getInstance(name, type);
    if(instance != null) {
        return instance;
    } else {
        IClientConfig config = (IClientConfig)this.getInstance(name, IClientConfig.class);
        return instantiateWithConfig(this.getContext(name), type, config);
    }
}

查看RibbonLoadBalancerClient.getLoadBalancer方法,它会调用SpringClientFactory.getInstance方法获取的LoadBalancer实例,整个context 的实例化过程是在SpringClientFactory的父类NamedContextFactory中完成的

public <T> T getInstance(String name, Class<T> type) {
    AnnotationConfigApplicationContext context = this.getContext(name);
    return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type).length > 0?context.getBean(type):null;
}
protected AnnotationConfigApplicationContext getContext(String name) {
    if(!this.contexts.containsKey(name)) {
        Map var2 = this.contexts;
        synchronized(this.contexts) {
            if(!this.contexts.containsKey(name)) {
                //创建容器,并以服务名称为key,保存在contexts的Map结构中
                this.contexts.put(name, this.createContext(name));
            }
        }
    }

    return (AnnotationConfigApplicationContext)this.contexts.get(name);
}
protected AnnotationConfigApplicationContext createContext(String name) {
    //创建context 对象,相当于重新新建了一个Spring容器
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    if(this.configurations.containsKey(name)) {
        Class[] var3 = ((NamedContextFactory.Specification)this.configurations.get(name)).getConfiguration();
        int entry = var3.length;

        for(int var5 = 0; var5 < entry; ++var5) {
            Class configuration = var3[var5];
            context.register(new Class[]{configuration});
        }
    }

    Iterator var9 = this.configurations.entrySet().iterator();

    while(true) {
        Entry var10;
        do {
            if(!var9.hasNext()) {
                /**向容器中注册PropertyPlaceholderAutoConfiguration和defaultConfigType(org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration)**/
                context.register(new Class[]{PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType});
                //设置环境变量ribbon.client.name的值
                context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(this.propertySourceName, Collections.singletonMap(this.propertyName, name)));
                if(this.parent != null) {
                    context.setParent(this.parent);
                    context.setClassLoader(this.parent.getClassLoader());
                }

                context.setDisplayName(this.generateDisplayName(name));
                //初始化容器
                context.refresh();
                return context;
            }

            var10 = (Entry)var9.next();
        } while(!((String)var10.getKey()).startsWith("default."));

        Class[] var11 = ((NamedContextFactory.Specification)var10.getValue()).getConfiguration();
        int var12 = var11.length;

        for(int var7 = 0; var7 < var12; ++var7) {
            Class configuration1 = var11[var7];
            context.register(new Class[]{configuration1});
        }
    }
}

在NamedContextFactory.getInstance方法中首先会去调用自己的getContext方法获取context,如果contexts的Map结构存在对应服务名称的context则返回,否则调用createContext方法创建AnnotationConfigApplicationContext,并以name(服务名称)为key,保存到contexts的Map结构中。在NamedContextFactory.createContext中,会创建AnnotationConfigApplicationContext,并设置需要注册到这个小型Spring容器中的Class类,即PropertyPlaceholderAutoConfiguration和defaultConfigType(RibbonClientConfiguration)两个对象,容器的环境变量ribbon.client.name(就是服务的名称,用于给RibbonClientConfiguration.name变量赋值,RibbonClientConfiguration.name变量上有一个@RibbonClientName注解,进入注解里面发现其实就是@Value("${ribbon.client.name}"))。RibbonClientConfiguration是一个配置类,它实例化了ILoadBalancer、IClientConfig、IRule(负载均衡的算法规则)、IPing(ping ip的规则)、ServerList<Server>、ServerListUpdater等,获取到context之后,通过context.getBean方法获得ILoadBalancer对象。

protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
    return loadBalancer == null?null:loadBalancer.chooseServer(hint != null?hint:"default");
}
protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
    return loadBalancer == null?null:loadBalancer.chooseServer(hint != null?hint:"default");
}
public Server chooseServer(Object key) {
    if(this.counter == null) {
        this.counter = this.createCounter();
    }

    this.counter.increment();
    if(this.rule == null) {
        return null;
    } else {
        try {
            return this.rule.choose(key);
        } catch (Exception var3) {
            logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", new Object[]{this.name, key, var3});
            return null;
        }
    }
}

回到RibbonLoadBalancerClient.execute方法,获取到服务名称对应的ILoadBalancer后,调用RibbonLoadBalancerClient.getServer方法,即通过BaseLoadBalancer.chooseServer方法选择合适的服务器,BaseLoadBalancer.chooseServer通过调用配置的IRule实现类的choose方法,选择合适的服务器。

ILoadBalancer选择服务器的逻辑基本看完,那么每个ILoadBalancer的服务器列表是如何维护的?当某个服务器下线了,ILoadBalancer如何将它从可用的服务器列表中删除?

以DynamicServerListLoadBalancer为例,

public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping, ServerList<T> serverList, ServerListFilter<T> filter, ServerListUpdater serverListUpdater) {
    super(clientConfig, rule, ping);
    this.isSecure = false;
    this.useTunnel = false;
    this.serverListUpdateInProgress = new AtomicBoolean(false);
    this.updateAction = new UpdateAction() {//更新服务器列表的操作类
        public void doUpdate() {
            DynamicServerListLoadBalancer.this.updateListOfServers();
        }
    };
    this.serverListImpl = serverList;
    this.filter = filter;
    this.serverListUpdater = serverListUpdater;
    if(filter instanceof AbstractServerListFilter) {
        ((AbstractServerListFilter)filter).setLoadBalancerStats(this.getLoadBalancerStats());
    }
    this.restOfInit(clientConfig);
}
void restOfInit(IClientConfig clientConfig) {
    boolean primeConnection = this.isEnablePrimingConnections();
    this.setEnablePrimingConnections(false);
    this.enableAndInitLearnNewServersFeature();
    this.updateListOfServers();
    if(primeConnection && this.getPrimeConnections() != null) {
        this.getPrimeConnections().primeConnections(this.getReachableServers());
    }
    this.setEnablePrimingConnections(primeConnection);
    LOGGER.info("DynamicServerListLoadBalancer for client {} initialized: {}", clientConfig.getClientName(), this.toString());
}
public void enableAndInitLearnNewServersFeature() {
    LOGGER.info("Using serverListUpdater {}", this.serverListUpdater.getClass().getSimpleName());
    this.serverListUpdater.start(this.updateAction);
}

在DynamicServerListLoadBalancer的构造方法中,初始化了UpdateAction这个更新服务列表的操作类,然后调用restOfInit方法,在restOfInit调用enableAndInitLearnNewServersFeature,通过serverListUpdater.start开启了一个定时器,用于定时执行updateAction.doUpdate操作,更新服务器列表,serverListUpdater(PollingServerListUpdater)是在RibbonClientConfiguration.ribbonServerListUpdater中初始化的

public void enableAndInitLearnNewServersFeature() {
    LOGGER.info("Using serverListUpdater {}", this.serverListUpdater.getClass().getSimpleName());
    this.serverListUpdater.start(this.updateAction);
}
public synchronized void start(final UpdateAction updateAction) {
    if(this.isActive.compareAndSet(false, true)) {
        Runnable wrapperRunnable = new Runnable() {
            public void run() {
                if(!PollingServerListUpdater.this.isActive.get()) {
                    if(PollingServerListUpdater.this.scheduledFuture != null) {
                        PollingServerListUpdater.this.scheduledFuture.cancel(true);
                    }

                } else {
                    try {
                        updateAction.doUpdate();
                        PollingServerListUpdater.this.lastUpdated = System.currentTimeMillis();
                    } catch (Exception var2) {
                        PollingServerListUpdater.logger.warn("Failed one update cycle", var2);
                    }

                }
            }
        };
        this.scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(wrapperRunnable, this.initialDelayMs, this.refreshIntervalMs, TimeUnit.MILLISECONDS);
    } else {
        logger.info("Already active, no-op");
    }

}

查看PollingServerListUpdater.start方法,其创建了一个定时器,默认每隔30秒去执行updateAction.doUpdate()方法,updateAction是在DynamicServerListLoadBalancer的构造函数中创建的,其实就是调用了

DynamicServerListLoadBalancer.this.updateListOfServers()方法

@VisibleForTesting
public void updateListOfServers() {
    Object servers = new ArrayList();
    if(this.serverListImpl != null) {
        servers = this.serverListImpl.getUpdatedListOfServers();
        LOGGER.debug("List of Servers for {} obtained from Discovery client: {}", this.getIdentifier(), servers);
        if(this.filter != null) {
            servers = this.filter.getFilteredListOfServers((List)servers);
            LOGGER.debug("Filtered List of Servers for {} obtained from Discovery client: {}", this.getIdentifier(), servers);
        }
    }
    this.updateAllServerList((List)servers);
}
protected void updateAllServerList(List<T> ls) {
    if(this.serverListUpdateInProgress.compareAndSet(false, true)) {
        try {
            Iterator var2 = ls.iterator();
            while(var2.hasNext()) {
                Server s = (Server)var2.next();
                s.setAlive(true);
            }
            //设置allServerList所有的服务器列表
            this.setServersList(ls);
            //通过IPingStrategy策略,设置upServerList可用的服务器列表
            super.forceQuickPing();
        } finally {
            this.serverListUpdateInProgress.set(false);
        }
    }
}
public void setServersList(List lsrv) {
    //调用父类BaseLoadBalancer的setServersList,设置allServerList所有的服务器列表
    super.setServersList(lsrv);
    HashMap serversInZones = new HashMap();
    Iterator var4 = lsrv.iterator();
    while(var4.hasNext()) {
        Server server = (Server)var4.next();
        this.getLoadBalancerStats().getSingleServerStat(server);
        String zone = server.getZone();
        if(zone != null) {
            zone = zone.toLowerCase();
            Object servers = (List)serversInZones.get(zone);
            if(servers == null) {
                servers = new ArrayList();
                serversInZones.put(zone, servers);
            }

            ((List)servers).add(server);
        }
    }

    this.setServerListForZones(serversInZones);
}

在updateListOfServers方法中首先调用serverListImpl(ConfigurationBasedServerList)的getUpdatedListOfServers方法,获取所有的服务类列表,然后调用ConfigurationBasedServerList.updateAllServerList方法,ConfigurationBasedServerList.updateAllServerList最终会调用BaseLoadBalancer.setServersList设置allServerList(所有的服务器列表),回到DynamicServerListLoadBalancer.updateAllServerList方法,设置完allServerList后继续调用super.forceQuickPing(即BaseLoadBalancer.setServersList)方法,通过ping ip的策略,设置upServerList(可用的服务列表)。

猜你喜欢

转载自blog.csdn.net/qq_33513289/article/details/107884871