【一塊兒學源碼-微服務】Ribbon 源碼二:經過Debug找出Ribbon初始化流程及ILoadBalancer原理分析

前言

前情回顧

上一講講了Ribbon的基礎知識,經過一個簡單的demo看了下Ribbon的負載均衡,咱們在RestTemplate上加了@LoadBalanced註解後,就可以自動的負載均衡了。java

本講目錄

這一講主要是繼續深刻RibbonLoadBalancerClient和Ribbon+Eureka整合的方式。spring

上文咱們已經知道調用RestTemplate時,會在其上面加上一個LoadBalancerInterceptor攔截器,其中會先執行LoadBalancerClient.execute()方法。微信

這裏咱們會有一個疑問,默認的LoadBalancerInterceptorLoadBalancerClient都是什麼呢?他們分別在哪裏進行初始化的呢?負載均衡

帶着這些疑問咱們來往前遞推下Ribbon初始化過程,相信看完下面的分析後,這些問題也就迎刃而解了。ide

目錄以下:函數

  1. 從XXXAutoConfig來追溯Ribbon初始化過程
  2. ZoneAwareLoadBalancer原理分析

說明

原創不易,如若轉載 請標明來源!this

博客地址:一枝花算不算浪漫
微信公衆號:壹枝花算不算浪漫debug

源碼閱讀

從XXXAutoConfig來追溯Ribbon初始化過程

在第一篇文章咱們已經分析了,和LoadBalanced類同目錄下有一個LoadBalancerAutoConfiguration類,這個是咱們最早找到的負載均衡自動配置類。code

LoadBalancerAutoConfiguration做用

這個配置類主要是爲調用的RestTemplate調用時添加LoadBalancerInterceptor過濾器,裏面還有其餘一些重試的配置,這個後面再看。server

查看此類的依賴,能夠追蹤到:RibbonAutoConfiguration, 如圖所示:

RibbonAutoConfiguration做用
  1. 初始化SpringClientFactory
  2. 初始化LoadBalancerClient: RibbonLoadBalancerClient

其中在SpringClientFactory構造函數中有以下代碼:

public class SpringClientFactory extends NamedContextFactory<RibbonClientSpecification> {

    public SpringClientFactory() {
        super(RibbonClientConfiguration.class, NAMESPACE, "ribbon.client.name");
    }
}

看到這裏實際上會初始化RibbonClientConfiguration配置類,接着往下看。

RibbonClientConfiguration做用
  1. 初始化ribbonRule: ZoneAvoidanceRule
  2. 初始化ribbonPing:DummyPing
  3. 初始化ribbonServerList:ConfigurationBasedServerList
  4. 初始化ServerListUpdater:new PollingServerListUpdater(config)
  5. 初始化ILoadBalancer:ZoneAwareLoadBalancer
  6. 初始化ribbonServerListFilter:ZonePreferenceServerListFilter
  7. 初始化ribbonLoadBalancerContext:RibbonLoadBalancerContext
  8. 初始化serverIntrospector:DefaultServerIntrospector

最後總結爲下面一張圖所示:

22.png

ZoneAwareLoadBalancer原理分析

咱們上面已經知道了Ribbon的大體流程,這裏咱們能夠看到默認的ILoadBalancerZoneAwareLoadBalancer,仍是回到以前RibbonLoadBalancerClient.execute() 方法中去,看下這裏方法:

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

    return execute(serviceId, ribbonServer, request);
}

這裏第一行代碼會獲取一個ILoadBalancer 咱們其實已經知道了,這裏默認的ILoadBalancerZoneAwareLoadBalancer

咱們接着看下 RibbonLoadBalancerClient 中的getLoadBalancer() 方法具體是怎麼獲取這個默認的LoadBalancer的。

這裏面使用的是SpringClientFactory.getLoadBalancer() 方法,而後一直往裏面跟, 最後調用到 NameContextFactory.java 中:

public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
        implements DisposableBean, ApplicationContextAware {

    private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();

    public <T> T getInstance(String name, Class<T> type) {
        AnnotationConfigApplicationContext context = getContext(name);
        if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
                type).length > 0) {
            return context.getBean(type);
        }
        return null;
    }

    protected AnnotationConfigApplicationContext getContext(String name) {
        if (!this.contexts.containsKey(name)) {
            synchronized (this.contexts) {
                if (!this.contexts.containsKey(name)) {
                    this.contexts.put(name, createContext(name));
                }
            }
        }
        return this.contexts.get(name);
    }
}

對每一個服務名稱,你要調用的每一個服務,對應的服務名稱,都有一個對應的spring的ApplicationContext容器,ServiceA對應着一個本身的獨立的spring的ApplicationContext容器

好比說要獲取這個ServiceA服務的LoadBalancer,那麼就從ServiceCA服務對應的本身的ApplicationContext容器中去獲取本身的LoadBalancer便可

若是是另一個ServiceC服務,那麼又是另外的一個spring APplicationContext,而後從裏面獲取到的LoadBalancer都是本身的容器裏的LoadBalancer

能夠經過debug 查看到下圖返回的LoadBanlancer信息。這裏就不在多贅述。

上面最後圖片能夠看到,實例化出來的instance是ZoneAwareLoadBalancer , 這個類繼承自DynamicServerListLoadBalancer,順帶看下類結構:

到了這裏就算是分析完了,再深究ZoneAwareLoadBalancer 就到了和Eureka整合相關的了,這一部分放到下一講繼續講解了。

總結

用一張圖作最後的總結:

申明

本文章首發自本人博客:https://www.cnblogs.com/wang-meng 和公衆號:壹枝花算不算浪漫,如若轉載請標明來源!

感興趣的小夥伴可關注我的公衆號:壹枝花算不算浪漫

22.jpg

相關文章
相關標籤/搜索