Dubbo路由機制概述

上一節咱們主要講解了利用dubbo-admin如何進行參數的動態修改,本節將重點介紹集羣實現中另一個實現細節:路由機制,Dubbo的路由機制主要解決的目的就是服務調用時,從已知的全部服務提供者中根據路由規則刷選服務提供者。架構

一、Dubbo路由機制概述

如下內容來源於官方文檔: 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述併發

以上是Dubbo 路由機制的基本知識,接下來從源碼的角度分析一下其實現原理。分佈式

二、Router相關類圖

這裏寫圖片描述

  1. Router:dubbo路由接口類 ● URL getUrl() :獲取路由配置URL。 ● < T> List< Invoker< T>> route(List< Invoker< T>> invokers, URL url, Invocation invocation) :根據路由規則返回符合規則的服務調用者。
  2. ConditionRouter:條件路由規則。
  3. ScriptRouter:腳本路由規則(JavaScript)。

2.1 如何添加路由規則

能夠經過dubbo-admin管理後臺,動態添加路由規則,其界面如圖所示: 這裏寫圖片描述高併發

點擊保存後,使用URL描述一條路由規則,並將存儲在註冊中心${service}/routers目錄下,而後通知相關訂閱者(服務消費者【調用方】)。 具體調用的方法爲RegistryDirecotry#notify方法,其片斷以下:源碼分析

// routers
if (routerUrls != null &amp;&amp; !routerUrls.isEmpty()) {  // @1
     List<router> routers = toRouters(routerUrls);     // @2
     if (routers != null) { // null - do nothing           
          setRouters(routers);                                        // @3
      }
}

代碼@1:若是routerUrls 不爲空,說明註冊中心的catalog=routers目錄下新增或刪除了某些路由規則,最後存在路由規則。 代碼@2:將路由規則URL轉換爲路由實現類Router接口的實現類,例如條件路由規則、腳本路由規則具體實現類。 代碼@3:將現存的路由規則實現類覆蓋RegistroyDirectory#routers屬性,在下一次服務調用時,這些路由規則將生效。this

咱們見到看一下toRouter方法的實現:url

RegistryDirectory#toRouters.net

private List<router> toRouters(List<url> urls) {
        List<router> routers = new ArrayList<router>();
        if (urls == null || urls.isEmpty()) {
            return routers;
        }
        if (urls != null &amp;&amp; !urls.isEmpty()) {
            for (URL url : urls) {
                if (Constants.EMPTY_PROTOCOL.equals(url.getProtocol())) {
                    continue;
                }
                String routerType = url.getParameter(Constants.ROUTER_KEY);
                if (routerType != null &amp;&amp; routerType.length() &gt; 0) {
                    url = url.setProtocol(routerType);
                }
                try {
                    Router router = routerFactory.getRouter(url);
                    if (!routers.contains(router))
                        routers.add(router);
                } catch (Throwable t) {
                    logger.error("convert router url to router error, url: " + url, t);
                }
            }
        }
        return routers;
    }

方法實現比較簡單,就是基於協議頭condition://或script://構建具體的路由規則實現類。 從上面兩個方法能夠看出,當主從中心的路由配置發生變化後,會從新構建RegistryDirectory的List< Router> routers屬性,那這個屬性在何時用呢?3d

AbstractDirectory#listcode

public List<invoker<t>&gt; list(Invocation invocation) throws RpcException {
        if (destroyed) {
            throw new RpcException("Directory already destroyed .url: " + getUrl());
        }
        List<invoker<t>&gt; invokers = doList(invocation);
        List<router> localRouters = this.routers; // local reference
        if (localRouters != null &amp;&amp; !localRouters.isEmpty()) {
            for (Router router : localRouters) {
                try {
                    if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY, false)) {
                        invokers = router.route(invokers, getConsumerUrl(), invocation);
                    }
                } catch (Throwable t) {
                    logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
                }
            }
        }
        return invokers;
    }

在經過RegistryDirector時,獲取List< Invoker>時,會對全部的Invoker列表進行路由過濾,而後返回符合路由規則的Invoker,本文就不相信分析Dubbo是如何根據配置的條件路由規則、腳本路由規則去過濾,其實現細節,若有興趣,可關注:ConditionRouter、ScriptRouter。


做者介紹:丁威,《RocketMQ技術內幕》做者,RocketMQ 社區佈道師,公衆號:中間件興趣圈 維護者,目前已陸續發表源碼分析Java集合、Java 併發包(JUC)、Netty、Mycat、Dubbo、RocketMQ、Mybatis等源碼專欄。能夠點擊連接:中間件知識星球,一塊兒探討高併發、分佈式服務架構,交流源碼。

</router></invoker<t></invoker<t></router></router></url></router></router>

相關文章
相關標籤/搜索