Dubbo3 路由規(guī)則

2022-04-02 15:12 更新

通過(guò) Dubbo 中的路由規(guī)則做服務(wù)治理

路由規(guī)則在發(fā)起一次RPC調(diào)用前起到過(guò)濾目標(biāo)服務(wù)器地址的作用,過(guò)濾后的地址列表,將作為消費(fèi)端最終發(fā)起RPC調(diào)用的備選地址。

  • 條件路由。支持以服務(wù)或 Consumer 應(yīng)用為粒度配置路由規(guī)則。
  • 標(biāo)簽路由。以 Provider 應(yīng)用為粒度配置路由規(guī)則。

后續(xù)我們計(jì)劃在 2.6.x 版本的基礎(chǔ)上繼續(xù)增強(qiáng)腳本路由功能。

條件路由

您可以隨時(shí)在服務(wù)治理控制臺(tái)  Dubbo-Admin 寫(xiě)入路由規(guī)則

簡(jiǎn)介

  • 應(yīng)用粒度
    # app1的消費(fèi)者只能消費(fèi)所有端口為20880的服務(wù)實(shí)例
    # app2的消費(fèi)者只能消費(fèi)所有端口為20881的服務(wù)實(shí)例
    ---
    scope: application
    force: true
    runtime: true
    enabled: true
    key: governance-conditionrouter-consumer
    conditions:
      - application=app1 => address=*:20880
      - application=app2 => address=*:20881
    ...
  • 服務(wù)粒度
    # DemoService的sayHello方法只能消費(fèi)所有端口為20880的服務(wù)實(shí)例
    # DemoService的sayHi方法只能消費(fèi)所有端口為20881的服務(wù)實(shí)例
    ---
    scope: service
    force: true
    runtime: true
    enabled: true
    key: org.apache.dubbo.samples.governance.api.DemoService
    conditions:
      - method=sayHello => address=*:20880
      - method=sayHi => address=*:20881
    ...

規(guī)則詳解

各字段含義

  • ?scope?表示路由規(guī)則的作用粒度,scope的取值會(huì)決定key的取值。必填。
    • service 服務(wù)粒度
    • application 應(yīng)用粒度
  • ?Key?明確規(guī)則體作用在哪個(gè)服務(wù)或應(yīng)用。必填。
    • scope=service時(shí),key取值為[{group}:]{service}[:{version}]的組合
    • scope=application時(shí),key取值為application名稱(chēng)
  • ?enabled=true? 當(dāng)前路由規(guī)則是否生效,可不填,缺省生效。
  • ?force=false ?當(dāng)路由結(jié)果為空時(shí),是否強(qiáng)制執(zhí)行,如果不強(qiáng)制執(zhí)行,路由結(jié)果為空的路由規(guī)則將自動(dòng)失效,可不填,缺省為 ?false?。
  • ?runtime=false? 是否在每次調(diào)用時(shí)執(zhí)行路由規(guī)則,否則只在提供者地址列表變更時(shí)預(yù)先執(zhí)行并緩存結(jié)果,調(diào)用時(shí)直接從緩存中獲取路由結(jié)果。如果用了參數(shù)路由,必須設(shè)為 ?true?,需要注意設(shè)置會(huì)影響調(diào)用的性能,可不填,缺省為 ?false?。
  • ?priority=1 ?路由規(guī)則的優(yōu)先級(jí),用于排序,優(yōu)先級(jí)越大越靠前執(zhí)行,可不填,缺省為 0。
  • ?conditions ?定義具體的路由規(guī)則內(nèi)容。必填。

Conditions規(guī)則體

`conditions`部分是規(guī)則的主體,由1到任意多條規(guī)則組成,下面我們就每個(gè)規(guī)則的配置語(yǔ)法做詳細(xì)說(shuō)明:

1.格式

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

    2.表達(dá)式

      參數(shù)支持:

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

      條件支持:

      • 等號(hào) ??表示"匹配",如:?host = 10.20.153.10?
      • 不等號(hào)? != ?表示"不匹配",如:?host != 10.20.153.10?

      值支持:

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

      3.Condition示例

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

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

        簡(jiǎn)介

        標(biāo)簽路由通過(guò)將某一個(gè)或多個(gè)服務(wù)的提供者劃分到同一個(gè)分組,約束流量只在指定分組中流轉(zhuǎn),從而實(shí)現(xiàn)流量隔離的目的,可以作為藍(lán)綠發(fā)布、灰度發(fā)布等場(chǎng)景的能力基礎(chǔ)。

        Provider

        標(biāo)簽主要是指對(duì)Provider端應(yīng)用實(shí)例的分組,目前有兩種方式可以完成實(shí)例分組,分別是?動(dòng)態(tài)規(guī)則打標(biāo)?和?靜態(tài)規(guī)則打標(biāo)?,其中動(dòng)態(tài)規(guī)則相較于靜態(tài)規(guī)則優(yōu)先級(jí)更高,而當(dāng)兩種規(guī)則同時(shí)存在且出現(xiàn)沖突時(shí),將以動(dòng)態(tài)規(guī)則為準(zhǔn)。

        • 動(dòng)態(tài)規(guī)則打標(biāo),可隨時(shí)在服務(wù)治理控制臺(tái)下發(fā)標(biāo)簽歸組規(guī)則
          # governance-tagrouter-provider應(yīng)用增加了兩個(gè)標(biāo)簽分組tag1和tag2
          # tag1包含一個(gè)實(shí)例 127.0.0.1:20880
          # tag2包含一個(gè)實(shí)例 127.0.0.1:20881
          ---
            force: false
            runtime: true
            enabled: true
            key: governance-tagrouter-provider
            tags:
              - name: tag1
                addresses: ["127.0.0.1:20880"]
              - name: tag2
                addresses: ["127.0.0.1:20881"]
           ...
        • 靜態(tài)打標(biāo)
          <dubbo:provider tag="tag1"/>
          或者
          <dubbo:service tag="tag1"/>
          或者
          java -jar xxx-provider.jar -Ddubbo.provider.tag={the tag you want, may come from OS ENV}

        Consumer

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

        請(qǐng)求標(biāo)簽的作用域?yàn)槊恳淮?invocation,使用 attachment 來(lái)傳遞請(qǐng)求標(biāo)簽,注意保存在 attachment 中的值將會(huì)在一次完整的遠(yuǎn)程調(diào)用中持續(xù)傳遞,得益于這樣的特性,我們只需要在起始調(diào)用時(shí),通過(guò)一行代碼的設(shè)置,達(dá)到標(biāo)簽的持續(xù)傳遞。

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

        規(guī)則詳解

        格式

        • ?Key?明確規(guī)則體作用到哪個(gè)應(yīng)用。必填。
        • ?enabled=true? 當(dāng)前路由規(guī)則是否生效,可不填,缺省生效。
        • ?force=false? 當(dāng)路由結(jié)果為空時(shí),是否強(qiáng)制執(zhí)行,如果不強(qiáng)制執(zhí)行,路由結(jié)果為空的路由規(guī)則將自動(dòng)失效,可不填,缺省為 ?false?。
        • ?runtime=false ?是否在每次調(diào)用時(shí)執(zhí)行路由規(guī)則,否則只在提供者地址列表變更時(shí)預(yù)先執(zhí)行并緩存結(jié)果,調(diào)用時(shí)直接從緩存中獲取路由結(jié)果。如果用了參數(shù)路由,必須設(shè)為 ?true?,需要注意設(shè)置會(huì)影響調(diào)用的性能,可不填,缺省為 ?false?。
        • ?priority=1 ?路由規(guī)則的優(yōu)先級(jí),用于排序,優(yōu)先級(jí)越大越靠前執(zhí)行,可不填,缺省為 0。
        • ?tags ?定義具體的標(biāo)簽分組內(nèi)容,可定義任意n(n>=1)個(gè)標(biāo)簽并為每個(gè)標(biāo)簽指定實(shí)例列表。必填。name, 標(biāo)簽名稱(chēng)
        • addresses, 當(dāng)前標(biāo)簽包含的實(shí)例列表

        降級(jí)約定

        1. ?dubbo.tag=tag1 ?時(shí)優(yōu)先選擇 標(biāo)記了?tag=tag1? 的 provider。若集群中不存在與請(qǐng)求標(biāo)記對(duì)應(yīng)的服務(wù),默認(rèn)將降級(jí)請(qǐng)求 tag為空的provider;如果要改變這種默認(rèn)行為,即找不到匹配tag1的provider返回異常,需設(shè)置?dubbo.force.tag=true?。
        2. ?dubbo.tag?未設(shè)置時(shí),只會(huì)匹配tag為空的provider。即使集群中存在可用的服務(wù),若 tag 不匹配也就無(wú)法調(diào)用,這與約定1不同,攜帶標(biāo)簽的請(qǐng)求可以降級(jí)訪問(wèn)到無(wú)標(biāo)簽的服務(wù),但不攜帶標(biāo)簽/攜帶其他種類(lèi)標(biāo)簽的請(qǐng)求永遠(yuǎn)無(wú)法訪問(wèn)到其他標(biāo)簽的服務(wù)。
        提示
        ?2.6.x ?版本以及更早的版本請(qǐng)使用老版本路由規(guī)則
        自定義路由參考路由擴(kuò)展


        以上內(nèi)容是否對(duì)您有幫助:
        在線筆記
        App下載
        App下載

        掃描二維碼

        下載編程獅App

        公眾號(hào)
        微信公眾號(hào)

        編程獅公眾號(hào)