Router服務路由, 根據路由規則從多個Invoker中選出一個子集AbstractDirectory是所有目錄服務實現的上層抽象, 它在list列舉出所有invokers後,會在通過Router服務進行路由過濾。
Router接口定義
public interface Router extendsComparable<Router> {
URL getUrl();
<T> List<Invoker<T>> route(List<Invoker<T>>invokers, URL url, Invocation invocation)throws RpcException;
}
ConditionRouter: 條件路由
我們這裏簡單分析下代碼實現具體功能參考官方文檔
條件表達式以 => 分割爲whenRule和thenRule
ConditionRouter創建,構造器初始
1)從url根據RULE_KEY獲取路由條件路由內容
2)rule.indexOf("=>") 分割路由內容
3)分別調用parseRule(rule) 解析路由爲whenRule和thenRules
ConditionRouter執行route方法
1)如果url不滿足when條件即過來條件, 不過濾返回所有invokers
2)遍歷所有invokers判斷是否滿足then條件, 將滿足條件的加入集合result
3)Result不爲空,有滿足條件的invokers返回
4)Result爲空, 沒有滿足條件的invokers, 判斷參數FORCE_KEY是否強制過來,如果強制過濾返回空, 不是返回所有即不過濾
ScriptRouter: 腳本路由,
通過url的RULE_KEY參數獲取腳本內容,然後通過java的腳本引擎執行腳本代碼, dubbo的測試用例都是通過javascript作爲腳本但是理論上也支持groovy, jruby腳本,大家可以參考下測試用例ScriptRouterTest。
ScriptRouter創建,構造器初始化
1)從url獲取腳本類型javascript, groovy等等
2)從url根據RULE_KEY獲取路由規則內容
3)根據腳本類型獲取java支持的腳本執行引擎
ScriptRouter執行route方法
1)執行引擎創建參數綁定
2)綁定執行的參數
3)執行引擎編譯路由規則得到執行函數CompiledScript
4)CompiledScript.eval(binds) 根據參數執行路由規則
Dubbo提供了ConditionRouterFactory, ScriptRouterFactory來創建對應的路由,路由的規則從url的RULE_KEY參數來獲取,路由規則可以通過監控中心或者治理中心寫入註冊中心
RegistryFactory registryFactory =ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry =registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181");
registry.register(URL.valueOf("condition://0.0.0.0/com.foo.BarService?category=routers&dynamic=false&rule="+ URL.encode("http://10.20.160.198/wiki/display/dubbo/host = 10.20.153.10=> host = 10.20.153.11") + "));
Dubbo也支持通過FileRouterFactory從文件讀取路由規則,將讀取的規則設置到url的RULE_KEY參數上, 文件的後綴代表了路由的類型,選擇具體的路由工廠 ConditionRouterFactory,ScriptRouterFactory來創建路由規則