Dubbo3 舊路由規(guī)則

2022-04-01 11:08 更新

在 Dubbo 2.6.x版本以及更早的版本中配置路由規(guī)則

路由規(guī)則 (2.2.0 以上版本支持 )決定一次 dubbo 服務(wù)調(diào)用的目標(biāo)服務(wù)器,分為條件路由規(guī)則和腳本路由規(guī)則,并且支持可擴展 (路由規(guī)則擴展點:路由擴展)。

寫入路由規(guī)則

向注冊中心寫入路由規(guī)則的操作通常由監(jiān)控中心或治理中心的頁面完成

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")));

其中:

  • ?route://? 表示路由規(guī)則的類型,支持條件路由規(guī)則和腳本路由規(guī)則,可擴展,必填。
  • ?0.0.0.0 ?表示對所有 IP 地址生效,如果只想對某個 IP 的生效,請?zhí)钊刖唧w IP,必填。
  • ?com.foo.BarService ?表示只對指定服務(wù)生效,必填。
  • ?group=foo? 對指定服務(wù)的指定group生效,不填表示對未配置group的指定服務(wù)生效
  • ?version=1.0?對指定服務(wù)的指定version生效,不填表示對未配置version的指定服務(wù)生效
  • ?category=routers? 表示該數(shù)據(jù)為動態(tài)配置類型,必填。
  • ?dynamic=false? 表示該數(shù)據(jù)為持久數(shù)據(jù),當(dāng)注冊方退出時,數(shù)據(jù)依然保存在注冊中心,必填。
  • ?enabled=true ?覆蓋規(guī)則是否生效,可不填,缺省生效。
  • ?force=false ?當(dāng)路由結(jié)果為空時,是否強制執(zhí)行,如果不強制執(zhí)行,路由結(jié)果為空的路由規(guī)則將自動失效,可不填,缺省為 ?false?。
  • ?runtime=false? 是否在每次調(diào)用時執(zhí)行路由規(guī)則,否則只在提供者地址列表變更時預(yù)先執(zhí)行并緩存結(jié)果,調(diào)用時直接從緩存中獲取路由結(jié)果。如果用了參數(shù)路由,必須設(shè)為 true,需要注意設(shè)置會影響調(diào)用的性能,可不填,缺省為 ?false?。
  • ?priority=1 ?路由規(guī)則的優(yōu)先級,用于排序,優(yōu)先級越大越靠前執(zhí)行,可不填,缺省為 0。
  • ?rule=URL.encode("host = 10.20.153.10 => host = 10.20.153.11")? 表示路由規(guī)則的內(nèi)容,必填。

條件路由規(guī)則

基于條件表達式的路由規(guī)則,如:?host = 10.20.153.10 => host = 10.20.153.11?

規(guī)則:

  • ?=>? 之前的為消費者匹配條件,所有參數(shù)和消費者的 URL 進行對比,當(dāng)消費者滿足匹配條件時,對該消費者執(zhí)行后面的過濾規(guī)則。
  • ?=> ?之后為提供者地址列表的過濾條件,所有參數(shù)和提供者的 URL 進行對比,消費者最終只拿到過濾后的地址列表。
  • 如果匹配條件為空,表示對所有消費方應(yīng)用,如:?=> host != 10.20.153.11?
  • 如果過濾條件為空,表示禁止訪問,如:?host = 10.20.153.10 =>?

表達式:

參數(shù)支持:

  • 服務(wù)調(diào)用信息,如:method, argument 等,暫不支持參數(shù)路由
  • URL 本身的字段,如:protocol, host, port 等
  • 以及 URL 上的所有參數(shù),如:application, organization 等

條件支持:

  • 等號 ?=? 表示"匹配",如:?host = 10.20.153.10?
  • 不等號? !=? 表示"不匹配",如:?host != 10.20.153.10?

值支持:

  • 以逗號? , ?分隔多個值,如:?host != 10.20.153.10,10.20.153.11?
  • 以星號? * ?結(jié)尾,表示通配,如:?host != 10.20.*?
  • 以美元符 ?$? 開頭,表示引用消費者參數(shù),如:?host = $host?

示例:

  1. 排除預(yù)發(fā)布機:
    ?=> host != 172.22.3.91?
    
  2. 白名單 (注意:一個服務(wù)只能有一條白名單規(guī)則,否則兩條規(guī)則交叉,就都被篩選掉了):
    host != 10.20.153.10,10.20.153.11 =>?
  3. 黑名單:
    host = 10.20.153.10,10.20.153.11 =>?
  4. 服務(wù)寄宿在應(yīng)用上,只暴露一部分的機器,防止整個集群掛掉:
    => host = 172.22.3.1*,172.22.3.2*
  5. 為重要應(yīng)用提供額外的機器:
    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. 隔離不同機房網(wǎng)段:
    host != 172.22.3.* => host != 172.22.3.*
  9. 提供者與消費者部署在同集群內(nèi),本機只訪問本機的服務(wù):
    => host = $host

腳本路由規(guī)則

腳本路由規(guī)則(注意:腳本沒有沙箱約束,可執(zhí)行任意代碼,存在后門風(fēng)險) 支持 JDK 腳本引擎的所有腳本,比如:javascript, jruby, groovy 等,通過 type=javascript 參數(shù)設(shè)置腳本類型,缺省為 javascript。

"script://0.0.0.0/com.foo.BarService?category=routers&dynamic=false&rule=" + URL.encode("(function route(invokers) { ... } (invokers))")

基于腳本引擎的路由規(guī)則,如:

(function route(invokers) {
    var result = new java.util.ArrayList(invokers.size());
    for (i = 0; i < invokers.size(); i ++) {
        if ("10.20.153.10".equals(invokers.get(i).getUrl().getHost())) {
            result.add(invokers.get(i));
        }
    }
    return result;
} (invokers)); // 表示立即執(zhí)行方法

標(biāo)簽路由規(guī)則

標(biāo)簽路由規(guī)則 (該特性在 2.7.0 以上版本支持) ,當(dāng)應(yīng)用選擇裝配標(biāo)簽路由(TagRouter)之后,一次 dubbo 調(diào)用能夠根據(jù)請求攜帶的 tag 標(biāo)簽智能地選擇對應(yīng) tag 的服務(wù)提供者進行調(diào)用。

服務(wù)提供者

  1. 給應(yīng)用裝配標(biāo)簽路由器:
@Bean
public ApplicationConfig applicationConfig() {
    ApplicationConfig applicationConfig = new ApplicationConfig();
    applicationConfig.setName("provider-book");
    applicationConfig.setQosEnable(false);
    // instruct tag router
    Map<String,String> parameters = new HashMap<>();
    parameters.put(Constants.ROUTER_KEY, "tag");
    applicationConfig.setParameters(parameters);
    return applicationConfig;
}
  1. 給應(yīng)用設(shè)置具體的標(biāo)簽:
@Bean
public ProviderConfig providerConfig(){
	ProviderConfig providerConfig = new ProviderConfig();
	providerConfig.setTag("red");
	return providerConfig;
}

應(yīng)用未裝配 tag 屬性或服務(wù)提供者未設(shè)置 tag 屬性,都將被認(rèn)為是默認(rèn)的應(yīng)用,這些默認(rèn)應(yīng)用將會在調(diào)用無法匹配 provider 時當(dāng)作降級方案。

服務(wù)消費者

RpcContext.getContext().setAttachment(Constants.TAG_KEY,"red");

請求標(biāo)簽的作用域為每一次 invocation,使用 attachment 來傳遞請求標(biāo)簽,注意保存在 attachment 中的值將會在一次完整的遠程調(diào)用中持續(xù)傳遞,得益于這樣的特性,我們只需要在起始調(diào)用時,通過一行代碼的設(shè)置,達到標(biāo)簽的持續(xù)傳遞。

目前僅僅支持 hardcoding 的方式設(shè)置 dubboTag。注意到 RpcContext 是線程綁定的,優(yōu)雅的使用 TagRouter 特性,建議通過 servlet 過濾器(在 web 環(huán)境下),或者定制的 SPI 過濾器設(shè)置 dubboTag。

規(guī)則描述

  1. dubbo.tag=red 時優(yōu)先選擇 tag=red 的 provider。若集群中不存在與請求標(biāo)記對應(yīng)的服務(wù),可以降級請求 tag=null 的 provider,即默認(rèn) provider。
  2. dubbo.tag=null 時,只會匹配 tag=null 的 provider。即使集群中存在可用的服務(wù),若 tag 不匹配就無法調(diào)用,這與規(guī)則1不同,攜帶標(biāo)簽的請求可以降級訪問到無標(biāo)簽的服務(wù),但不攜帶標(biāo)簽/攜帶其他種類標(biāo)簽的請求永遠無法訪問到其他標(biāo)簽的服務(wù)。
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號