Dubbo3 路由規(guī)則

2022-04-02 15:12 更新

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

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

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

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

條件路由

您可以隨時在服務治理控制臺  Dubbo-Admin 寫入路由規(guī)則

簡介

  • 應用粒度
    # app1的消費者只能消費所有端口為20880的服務實例
    # app2的消費者只能消費所有端口為20881的服務實例
    ---
    scope: application
    force: true
    runtime: true
    enabled: true
    key: governance-conditionrouter-consumer
    conditions:
      - application=app1 => address=*:20880
      - application=app2 => address=*:20881
    ...
  • 服務粒度
    # DemoService的sayHello方法只能消費所有端口為20880的服務實例
    # DemoService的sayHi方法只能消費所有端口為20881的服務實例
    ---
    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的取值會決定key的取值。必填。
    • service 服務粒度
    • application 應用粒度
  • ?Key?明確規(guī)則體作用在哪個服務或應用。必填。
    • scope=service時,key取值為[{group}:]{service}[:{version}]的組合
    • scope=application時,key取值為application名稱
  • ?enabled=true? 當前路由規(guī)則是否生效,可不填,缺省生效。
  • ?force=false ?當路由結果為空時,是否強制執(zhí)行,如果不強制執(zhí)行,路由結果為空的路由規(guī)則將自動失效,可不填,缺省為 ?false?。
  • ?runtime=false? 是否在每次調用時執(zhí)行路由規(guī)則,否則只在提供者地址列表變更時預先執(zhí)行并緩存結果,調用時直接從緩存中獲取路由結果。如果用了參數路由,必須設為 ?true?,需要注意設置會影響調用的性能,可不填,缺省為 ?false?。
  • ?priority=1 ?路由規(guī)則的優(yōu)先級,用于排序,優(yōu)先級越大越靠前執(zhí)行,可不填,缺省為 0。
  • ?conditions ?定義具體的路由規(guī)則內容。必填。

Conditions規(guī)則體

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

1.格式

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

    2.表達式

      參數支持:

      • 服務調用信息,如: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?

      3.Condition示例

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

        標簽路由規(guī)則

        簡介

        標簽路由通過將某一個或多個服務的提供者劃分到同一個分組,約束流量只在指定分組中流轉,從而實現流量隔離的目的,可以作為藍綠發(fā)布、灰度發(fā)布等場景的能力基礎。

        Provider

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

        • 動態(tài)規(guī)則打標,可隨時在服務治理控制臺下發(fā)標簽歸組規(guī)則
          # governance-tagrouter-provider應用增加了兩個標簽分組tag1和tag2
          # tag1包含一個實例 127.0.0.1:20880
          # tag2包含一個實例 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)打標
          <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");
        

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

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

        規(guī)則詳解

        格式

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

        降級約定

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


        以上內容是否對您有幫助:
        在線筆記
        App下載
        App下載

        掃描二維碼

        下載編程獅App

        公眾號
        微信公眾號

        編程獅公眾號