可在控制面對服務的路由進行精細控制,是一個成熟 RPC 系統必備的能力之一。作爲一個逐步走向成熟的 RPC 系統,Apache/dubbo-go(以下簡稱 dubbo-go )的最新版本 v1.4 中已經實現了 Condition Router 和 Health Instance First Router 等路由。
實現一個功能,首先要清楚其本質。那到底什麼是路由規則,我們爲什麼需要路由規則?設想這麼一個場景:現在要對某服務的新版本進行一次灰度發佈,需要將一些對實驗流量進行引流到灰度機器,其餘流量依舊使用正常服務。此時就可以考慮使用路由策略達到目的。
路由規則( routing rule )是爲了改變網絡流量所經過的途徑而修改路由信息的技術,通過改變路由屬性(包括可達性)達到引流的目的。在發起一次 RPC 調用前,它會過濾目標服務器地址,將消費端最終發起 RPC 調用的目標範圍限定在過濾後的地址列表。
目標
路由策略的關鍵點在於:
1、設定規則:用戶可通過什麼方式把路由規則傳遞給使用方;
2、解析規則:涉及到的路由規則的語法,以及對語法的解析。比如,要考慮規則是否支持邏輯運算;
3、規則匹配:如何判斷一個服務實例是否匹配某條路由規則。
綜上,可以總結出 dubbo-go 路由規則的目標有:
1、支持從多個地方,如本地文件、遠程配置中心,讀取路由規則信息;
2、設計一套定義路由規則的簡單語法;
3、保持與 Dubbo 的兼容,降低學習成本;
總體設計
首先要考慮的是:路由規則應該放在整個服務治理週期的哪個階段呢?dubbo-go 的架構圖如下:
可以看到圖中的 Router 介於 Cluster 和 LB(load balance) 之間,這就意味着一個請求被髮送到哪個服務器,是經過了 Cluster - Router - LB 三層處理的。可以將 Router 看做是一種較小範圍的邏輯分組。
而在 Router 內部,將經歷三個步驟:讀取路由規則,解析路由規則,執行匹配。爲了提高程序效率,路由規則的讀取和解析都是可以提前完成的,比如在應用啓動的時候。
根據上面圖中流程,可清楚地明晰 Router 的路由流程。
接口設計
根據前面的目標和總體設計,我們很容易地設計出 Router 的接口。
路由規則接口
Router 是 dubbo-go 路由最核心的接口。它可以理解爲,當一個請求(或者說一次調用)過來的時候,判斷哪些實例是滿足該規則的抽象。其實際代碼定義如下:
其核心在於 Route 方法,執行匹配邏輯。目前該接口的實現有:
ListenableRouter
AppRouter
ConditionRouter
HealthCheckRouter
FileConditionRouter
在現實實現中,不同的不同的路由規則是有優先級的,即 Router 的另一個重要特性:Priority 。它決定了的是路由規則的組織方式。
路由規則鏈式接口
除了優先級,多個路由規則的執行是有順序的。有路由規則的 Chain 接口如下:
Chain 實現了對不同路由規則的組織。從命名也可以看出,它是責任鏈模式的一種應用,通過該接口可將路由規則組成一條鏈,鏈中每條規則的輸出都是下一條規則的輸入。至於整個鏈路中不同規則的順序,取決於每個規則的 Priority ,它決定了每條路由規則的排序。
讀取路由規則接口
讀取路由規則對應 FileRouterFactory 和 RouterFactory 兩個接口。一般地,只需要一個 RouterFactory 接口就可以,但考慮到路由規則的不同來源,比如規則可能是從配置文件裏面讀取過來,也可能是直接在服務的 URL 解析而來,所以我們抽象出來了兩個接口:
FileRouterFactory
RouterFactory
我們一般將這兩個接口對應本地和遠程兩種情況:
1、本地路由規則配置:在原配置加載階段,新增讀取路由配置文件步驟。使用 FileRouterFactory 解析後,生成對應路由規則,然後加載到緩存中。
2、遠程路由規則配置:讀取遠程配置並且監聽其變化,篩選符合路由規則配置信息,通過 RouterFactory 生成對應路由規則,同樣加載到緩存中備用。
實現
從圖裏面可以看出,實現路由規則以兼容 dubbo 爲首要目標,降低使用者的學習成本爲輔助目標。與配置中心模塊相結合,實現路由規則遠程統一管理與下發。
規則類型
下面介紹一下 dubbo-go 現有的路由規則實現。
條件路由
Condition Router 作爲 dubbo-go 中第一個支持的路由規則實現,允許用戶通過配置文件及配置中心管理路由規則。與之相似的一個概念是 dubbo-go 的 group,但是條件路由提供了更加細粒度的控制手段和更加豐富的表達語義。比較典型的使用場景是黑白名單設置,灰度以及測試等。
健康檢查路由
在 RPC 調用中,如果希望儘可能地將請求命中到那些處理能力快、處於健康狀態的實例,即可以考慮該路由。該路由判定斷定某個服務提供者的不健康度,優先調用那些健康的服務實例。對 "健康" 度的判定,dubbo-go 默認的實現策略是:某服務的錯誤比例到達某一個閾值或者請求活躍數大於上限,則認爲其不健康,頗類似於服務熔斷。dubbo-go 當然亦允許用戶擴展其健康檢測策略。
標籤路由
以 Provider 爲維度,將某一個或多個服務的提供者劃分到同一個分組,約束流量只在指定分組中流轉,從而實現流量隔離的目的,即爲標籤路由。它可以作爲藍綠髮布、灰度發佈等場景的能力基礎。
靜態打標:根據配置文件所配置的標籤,固定給 Provider 設置標籤。
動態打標:基於健康檢查路由,根據服務不同時刻,不同狀態,動態在 Provider 設置適合的標籤。
示例
下面以條件路由在 zookeeper 實現爲例,對服務提供者與服務消費者進行整體流程分析。
如何配置條件路由規則
可以直接通過 dubbo-admin 進行配置:
這些配置可以分成全局配置和服務配置兩類。
全局配置:
對應應用級全局路由規則配置。例如:
/dubbo/config/dubbo/user-info-server(應用名).condition-router
上面 schema 配置中,應用名配置爲爲 user-info-server,即該條規則只對該應用生效。後綴 ".condition-router" 表明該條規則爲條件路由。除此之外,還可用 ".tag-router" 表示標籤路由。
服務配置:
對應服務級所有路由規則配置。例如有如下規則 schema:
/dubbo/ com.ikurento.user.UserProvider(服務名) /routers
該規則中服務名爲 com.ikurento.user.UserProvider。
除了在控制面板 Dubbo Admin 中下發路由規則外,還可以在本地文件中配置相應的規則。比如說在文件 router_config.yml 中配置:
# dubbo router yaml configure filepriority: 1force: trueconditions : ["host = 1.1.1.1 => host = 192.168.199.214"]
更多配置方式請參考條件路由配置。使用 dubbo-go 的路由功能時,注意以以下方式 引入對應的包:
條件路由配置:
http://dubbo.apache.org/zh-cn/docs/user/demos/routing-rule.html
總結
dubbo-go 整體路由規則功能實現,已基本對齊 dubbo 2.7.x 版本,目前上文中描述過的條件路由、標籤路由與健康檢測路由,且支持本地及遠端配置路由規則,能滿足基本使用場景,但距離完善還有還長遠的路。dubbo-go 未來路由功能計劃如下:
1、更多的配置中心【如 etcd/consul 等】支持,理論上已經支持,但還沒測試;
2、service-router(未支持);
3、標籤路由-配置中心(未支持);
4、目前路由與配置中心結合的代碼,對新增路由規則並不友好,有一定接入成本。
本文對 dubbo-go 已有的路由功能進行了總結,至於源碼級的分析,本文不作展開。歡迎大家持續關注 dubbo-go 項目:
https://github.com/apache/dubbo-go
作者信息:
鄒毅賢,Github ID @zouyx,開源愛好者,就職於 SheIn 供應鏈部門,負責供應鏈開放平臺。
本文縮略圖:icon by cg尐愳
Tips:
# 點下“在看”❤️
# 然後,公衆號對話框內發送“杯刷”,試試手氣?????
# 本期獎品是來自淘寶心選的椰棕杯刷。