Dubbo版本
- Dubbo 2.6.7版本
- 官方文檔舊路由規則文檔中【標簽路由規則】存在描述錯誤。 https://github.com/apache/dubbo-website/issues/1022這是我提交的issue
簡介
-
路由規則決定Dubbo調用哪些目標服務器,分為條件路由規則和腳本路由規則
-
一般由監控中心(Dubbo-Admin)或者治理中心來配置路由規則
-
向注冊中心寫入路由規則的API方式
RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181")); registry.register( URL.valueOf("route://0.0.0.0/com.foo.BarService?category=routers&dynamic=false&rule=" + URL.encode("host = 10.20.153.10 => host = 10.20.153.11")));
-
URL參數說明
參數 描述 是否必填 route://
表示路由規則的類型,支持條件路由規則和腳本路由規則。可擴展 是
0.0.0.0
表示對所有 IP 地址生效,如果只想對某個 IP 的生效,請填入具體 IP 是
com.foo.BarService
表示只對指定服務生效 是
group=foo
對指定服務的指定group生效,不填表示對未配置group的指定服務生效 否
version=1.0
對指定服務的指定version生效,不填表示對未配置version的指定服務生效 否
category=routers
表示該數據為動態配置類型 是
dynamic=false
表示該數據為持久數據,當注冊方退出時,數據依然保存在注冊中心 是
enabled=true
覆蓋規則是否生效,可不填,缺省生效 否
force=false
當路由結果為空時,是否強制執行,如果不強制執行,路由結果為空的路由規則將自動失效,可不填,缺省為 false
。否
runtime=false
是否在每次調用時執行路由規則,否則只在提供者地址列表變更時預先執行並緩存結果,調用時直接從緩存中獲取路由結果。如果用了參數路由,必須設為 true
,需要注意設置會影響調用的性能,可不填,缺省為false
。否
priority=1
路由規則的優先級,用於排序,優先級越大越靠前執行。默認是0 否
rule=URL.encode("host = 10.20.153.10 => host = 10.20.153.11")
路由規則的內容 是
條件路由
-
規則:consumer匹配條件 => provider匹配條件
=>
之前的為消費者匹配條件,所有參數和消費者的 URL 進行對比,當消費者滿足匹配條件時,對該消費者執行后面的過濾規則。=>
之后為提供者地址列表的過濾條件,所有參數和提供者的 URL 進行對比,消費者最終只拿到過濾后的地址列表。- 如果匹配條件為空,表示對所有消費方應用,如:
=> host != 10.20.153.11
- 如果過濾條件為空,表示禁止訪問,如:
host = 10.20.153.10 =>
-
表達式
-
參數支持:
-
服務調用信息,如:method, argument 等,暫不支持參數路由
-
URL 本身的字段,如:protocol, host, port 等
-
以及 URL 上的所有參數,如:application, organization 等
-
-
條件支持:
- 等號
=
表示"匹配",如:host = 10.20.153.10
- 不等號
!=
表示"不匹配",如:host != 10.20.153.10
- 等號
-
值支持:
- 以逗號
,
分隔多個值,如:host != 10.20.153.10,10.20.153.11
- 以星號
*
結尾,表示通配,如:host != 10.20.*
- 以美元符
$
開頭,表示引用消費者參數,如:host = $host
- 以逗號
-
-
示例
1. 排除IP => host != 172.22.3.91 2. 白名單(一個服務只能有一條白名單規則,否則兩條規則交叉,就都被篩選掉了) host != 10.20.153.10,10.20.153.11 => 3. 黑名單: host = 10.20.153.10,10.20.153.11 => 4. 服務寄宿在應用上,只暴露一部分的機器,防止整個集群掛掉: => host = 172.22.3.1*,172.22.3.2* 5. 為重要應用提供額外的機器: application != kylin => host != 172.22.3.95,172.22.3.96 6. 讀寫分離: method = find*,list*,get*,is* => host = 172.22.3.94,172.22.3.95,172.22.3.96 method != find*,list*,get*,is* => host = 172.22.3.97,172.22.3.98 7.前后台分離: application = bops => host = 172.22.3.91,172.22.3.92,172.22.3.93 application != bops => host = 172.22.3.94,172.22.3.95,172.22.3.96 8. 隔離不同機房網段: host != 172.22.3.* => host != 172.22.3.* 9. 提供者與消費者部署在同集群內,本機只訪問本機的服務: => host = $host
-
端口
1. 只調用指定端口的服務 => port = 20881 => port = 20881,20882 2. ip和端口 => port = 20881,20882 & host = 172.16.117.33
標簽路由
-
當應用選擇裝配標簽路由(TagRouter)之后,一次 dubbo 調用能夠根據請求攜帶的 tag 標簽智能地選擇對應 tag 的服務提供者進行調用。
dubbo.tag=provder1
時優先選擇tag=provider1
的 provider。若集群中不存在與請求標記對應的服務,可以降級請求tag=null
的 provider,即默認 provider。dubbo.tag=null
時,只會匹配tag=null
的 provider。即使集群中存在可用的服務,若 tag 不匹配就無法調用,這與規則1不同,攜帶標簽的請求可以降級訪問到無標簽的服務,但不攜帶標簽/攜帶其他種類標簽的請求永遠無法訪問到其他標簽的服務
-
生產者配置
1. 應用設置標簽 <dubbo:application name="xml-demo-provider"> <dubbo:parameter key="qos.enable" value="false"/> <dubbo:parameter key="dubbo.tag" value="provder1"/> </dubbo:application> 2. provider設置標簽 <dubbo:provider tag="provder2"></dubbo:provider>
-
消費者配置
//dubbo.tag RpcContext.getContext().setAttachment(Constants.TAG_KEY, "provder1"); //dubbo.force.tag 如果設置為true,則不降級,否則降級為默認provider RpcContext.getContext().setAttachment(Constants.FORCE_USE_TAG, "provder1");
-
源碼分析
TagRouter#route
@Override public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException { // filter List<Invoker<T>> result = new ArrayList<Invoker<T>>(); // Dynamic param 獲取dubbo.tag String tag = RpcContext.getContext().getAttachment(Constants.TAG_KEY); // Tag request if (!StringUtils.isEmpty(tag)) { // Select tag invokers first for (Invoker<T> invoker : invokers) { if (tag.equals(invoker.getUrl().getParameter(Constants.TAG_KEY))) { result.add(invoker); } } } // If Constants.REQUEST_TAG_KEY unspecified or no invoker be selected, downgrade to normal invokers if (result.isEmpty()) { // Only forceTag = true force match, otherwise downgrade //如果dubbo.force.tag=true則不降級,否則降級為默認provider String forceTag = RpcContext.getContext().getAttachment(Constants.FORCE_USE_TAG); if (StringUtils.isEmpty(forceTag) || "false".equals(forceTag)) { for (Invoker<T> invoker : invokers) { if (StringUtils.isEmpty(invoker.getUrl().getParameter(Constants.TAG_KEY))) { result.add(invoker); } } } } return result; }
配置規則
-
覆蓋規則是 Dubbo 設計的在無需重啟應用的情況下,動態調整 RPC 調用行為的一種能力。可以通過監控中心或者治理中心向注冊中心寫入動態配置覆蓋規則
RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181")); registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&timeout=1000"));
-
URL參數說明
參數 描述 是否必填 override://
表示數據采用覆蓋方式,支持 override
和absent
是
0.0.0.0
表示對所有 IP 地址生效,如果只想覆蓋某個 IP 的數據,請填入具體 IP 是
com.foo.BarService
表示只對指定服務生效 是
category=configurators
表示該數據為動態配置類型 是
dynamic=false
表示該數據為持久數據,當注冊方退出時,數據依然保存在注冊中心 是
enabled=true
覆蓋規則是否生效,缺省生效 否
application=foo
表示只對指定應用生效,不填,表示對所有應用生效。 否
timeout=1000
表示將滿足以上條件的 timeout
參數的值覆蓋為 1000。如果想覆蓋其它參數,直接加在override
的 URL 參數上否
-
示例
-
禁用提供者:(通常用於臨時踢除某台提供者機器,相似的,禁止消費者訪問請使用路由規則)
override://10.20.153.10/com.foo.BarService?category=configurators&dynamic=false&disbaled=true
-
調整權重:(通常用於容量評估,缺省權重為 100)
override://10.20.153.10/com.foo.BarService?category=configurators&dynamic=false&weight=200
-
調整負載均衡策略:(缺省負載均衡策略為 random)
override://10.20.153.10/com.foo.BarService?category=configurators&dynamic=false&loadbalance=leastactive
-
服務降級:(通常用於臨時屏蔽某個出錯的非關鍵服務)
override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null
-