Dubbo源碼(六) – 服務路由

前言

本文基於Dubbo2.6.x版本,中文注釋版源碼已上傳github:xiaoguyu/dubbo

今天,來聊點短的,服務路由Router,本文講的是路由的調用路徑,不講路由的規則解析。想了解規則解析的可以去官方文檔:服務路由

Dubbo的路由,就是根據規則,規定了哪些服務消費者可調用哪些服務提供者。

怎麼用

我們可以在服務治理控制台Dubbo-Admin寫入路由規則。

安裝Dubbo-Admin

我是使用docker方式安裝的,命令如下:

docker run -d \
-p 9001:8080 \
-e admin.root.user.name=admin \
-e admin.root.user.password=admin \
-e admin.registry.address='zookeeper://127.0.0.1:2181' \
-e admin.config-center='zookeeper://127.0.0.1:2181' \
-e admin.metadata-report.address='zookeeper://127.0.0.1:2181' \
--name dubbo-admin  \
apache/dubbo-admin

-e部分的參數說明,看官方介紹Dubbo Admin配置說明

配置規則

瀏覽器localhost:9001訪問Dubbo-Admin控制台,菜單選擇 服務治理→條件路由

Untitled

點擊創建按鈕,填寫相關參數即可

Untitled

詳細參數請參考官方文檔:路由規則用法示例

源碼

先來看看類圖

Untitled

Router就是路由介面,其有3個實現類。

Router介面有3個方法:

  1. URL getUrl();

  2. List<Invoker> route(List<Invoker> invokers, URL url, Invocation invocation);

    路由的選擇方法,篩選出符合條件的invoker

  3. int getPriority();

    獲取優先順序,用於排序

訂閱

當在Dubbo-Admin中配置了路由規則,會在註冊中心的routes節點創建子節點,這裡就包含了路由配置的數據

Untitled

上一篇文章講服務目錄的時候,說過RegistryDirectory會訂閱providers、consumers、configurators、routers等節點的,這裡面就包含了routers

具體的轉換邏輯在RegistryDirectory#toRouters方法中

private List<Router> toRouters(List<URL> urls) {
    List<Router> routers = new ArrayList<Router>();
    if (urls == null || urls.isEmpty()) {
        return routers;
    }
    if (urls != null && !urls.isEmpty()) {
        for (URL url : urls) {
            if (Constants.EMPTY_PROTOCOL.equals(url.getProtocol())) {
                continue;
            }
            String routerType = url.getParameter(Constants.ROUTER_KEY);
            if (routerType != null && routerType.length() > 0) {
                url = url.setProtocol(routerType);
            }
            try {
                // 工廠生成route
                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;
}

routerFactory是自適應拓展類,此處我們設置的是條件路由,所以routerFactory實際上是ConditionRouterFactory

public class ConditionRouterFactory implements RouterFactory {

    public static final String NAME = "condition";

    @Override
    public Router getRouter(URL url) {
        return new ConditionRouter(url);
    }

}

這個route工廠也很簡單,就是創建了一個ConditionRouter,具體的解析邏輯都在其構造方法中。

規則過濾

路由的核心,就是Router介面的route方法,那麼route方法在哪裡被引用呢

  1. 服務目錄刷新invoker列表時

    當服務目錄訂閱註冊中心資訊時,會刷新invoker列表,此時會調用路由

    Untitled

  2. 消費者獲取invoker時

    消費者要向生產者發起調用時,依賴的是invoker,此時invoker的獲取,需要經過路由篩選

    Untitled

總結

本文講了服務路由的數據獲取以及調用過程。路由的核心就是篩選invoker


參考資料

Dubbo開發指南

Tags: