配置運作方式

深入解讀 Dubbo 配置方法和工作原理,包含配置格式、設計理念、來源、載入流程等。

以下是 Dubbo 屬性配置的範例 dubbo-spring-boot-samples

  ## application.properties

  # Spring boot application
  spring.application.name=dubbo-externalized-configuration-provider-sample

  # Base packages to scan Dubbo Component: @com.alibaba.dubbo.config.annotation.Service
  dubbo.scan.base-packages=com.alibaba.boot.dubbo.demo.provider.service

  # Dubbo Application
  ## The default value of dubbo.application.name is ${spring.application.name}
  ## dubbo.application.name=${spring.application.name}

  #Dubbo Protocol
  dubbo.protocol.name=dubbo
  dubbo.protocol.port=12345

  ## Dubbo Registry
  dubbo.registry.address=N/A

  ## service default version
  dubbo.provider.version=1.0.0

接下來,圍繞這個範例,我們從配置格式、配置來源和載入流程三個方面分析 Dubbo 配置的工作原理。

1. 配置格式

目前 Dubbo 支援的所有配置都是 .properties 格式,包含 -D外部化配置 等。.properties 中的所有配置項都遵循 基於路徑 的配置格式。

在 Spring 應用程式中,您也可以將屬性配置放在 application.yml 中,樹狀階層結構更易於閱讀。

# Application-level configuration (no id)
dubbo.{config-type}.{config-item}={config-item-value}

# Instance-level configuration (specify id or name)
dubbo.{config-type}s.{config-id}.{config-item}={config-item-value}
dubbo.{config-type}s.{config-name}.{config-item}={config-item-value}

# Service interface configuration
dubbo.service.{interface-name}.{config-item}={config-item-value}
dubbo.reference.{interface-name}.{config-item}={config-item-value}

# method configuration
dubbo.service.{interface-name}.{method-name}.{config-item}={config-item-value}
dubbo.reference.{interface-name}.{method-name}.{config-item}={config-item-value}

# Method argument configuration
dubbo.reference.{interface-name}.{method-name}.{argument-index}.{config-item}={config-item-value}

1.1 應用程式層級配置(無 id)

應用程式層級配置的格式為:配置類型單數前綴,無 id/name。

# Application-level configuration (no id)
dubbo.{config-type}.{config-item}={config-item-value}

類似 applicationmonitormetrics 等都屬於應用程式層級的元件,因此只允許配置單一實例;而 protocolregistry 等允許多個元件配置,當只需要單例配置時,採用本節描述的格式。常見範例如下

dubbo.application.name=demo-provider
dubbo.application.qos-enable=false

dubbo.registry.address=zookeeper://127.0.0.1:2181

dubbo.protocol.name=dubbo
dubbo.protocol.port=-1

1.2 實例層級配置(指定 id 或 name)

實例的屬性配置需要指定 id 或 name,其前綴格式為:配置類型複數前綴 + id/name。適用於 protocolregistry 等支援多個配置的元件。

# Instance-level configuration (specify id or name)
dubbo.{config-type}s.{config-id}.{config-item}={config-item-value}
dubbo.{config-type}s.{config-name}.{config-item}={config-item-value}
  • 如果沒有 id 或 name 的實例,框架會根據這裡列出的屬性建立配置元件實例。
  • 如果已經存在具有相同 id 或名稱的實例,框架將使用此處列出的屬性作為對現有實例配置的補充。詳細信息,請參閱 [屬性覆蓋](../principle#32-Attribute Override)。
  • 請參閱 [單數和複數配置比較表] (../principle#17-single and plural configuration item comparison table)

配置示例

dubbo.registries.unit1.address=zookeeper://127.0.0.1:2181
dubbo.registries.unit2.address=zookeeper://127.0.0.1:2182

dubbo.protocols.dubbo.name=dubbo
dubbo.protocols.dubbo.port=20880

dubbo.protocols.hessian.name=hessian
dubbo.protocols.hessian.port=8089

1.3 服務介面配置

dubbo.service.org.apache.dubbo.samples.api.DemoService.timeout=5000
dubbo.reference.org.apache.dubbo.samples.api.DemoService.timeout=6000

方法配置

方法配置格式

# method configuration
dubbo.service.{interface-name}.{method-name}.{config-item}={config-item-value}
dubbo.reference.{interface-name}.{method-name}.{config-item}={config-item-value}

# Method argument configuration
dubbo.reference.{interface-name}.{method-name}.{argument-index}.{config-item}={config-item-value}

範例方法配置

dubbo.reference.org.apache.dubbo.samples.api.DemoService.sayHello.timeout=7000
dubbo.reference.org.apache.dubbo.samples.api.DemoService.sayHello.oninvoke=notifyService.onInvoke
dubbo.reference.org.apache.dubbo.samples.api.DemoService.sayHello.onreturn=notifyService.onReturn
dubbo.reference.org.apache.dubbo.samples.api.DemoService.sayHello.onthrow=notifyService.onThrow
dubbo.reference.org.apache.dubbo.samples.api.DemoService.sayHello.0.callback=true

等效於 XML 配置

<dubbo:reference interface="org.apache.dubbo.samples.api.DemoService">
    <dubbo:method name="sayHello" timeout="7000" oninvoke="notifyService.onInvoke"
                  onreturn="notifyService.onReturn" onthrow="notifyService.onThrow">
        <dubbo:argument index="0" callback="true" />
    </dubbo:method>
</dubbo:reference>

1.4 參數配置

參數 parameters 是一個映射對象,支持 xxx.parameters=[{key:value},{key:value}] 形式的配置。

dubbo.application.parameters=[{item1:value1},{item2:value2}]
dubbo.reference.org.apache.dubbo.samples.api.DemoService.parameters=[{item3:value3}]

1.5 傳輸層配置

Triple 協議使用 Http2 作為底層通信協議,允許用戶自定義 Http2 的 [6 個設置參數] (https://datatracker.ietf.org/doc/html/rfc7540#section-6.5.2)

配置格式如下

# Notify the peer header of the upper limit of compressed index tables
dubbo.rpc.tri.header-table-size=4096

# Enable server-side push function
dubbo.rpc.tri.enable-push=false

# Notify the peer of the maximum number of concurrent streams allowed
dubbo.rpc.tri.max-concurrent-streams=2147483647

# Declare the window size of the sender
dubbo.rpc.tri.initial-window-size=1048576

# Set the maximum number of bytes for the frame
dubbo.rpc.tri.max-frame-size=32768

# Notify the peer of the maximum number of uncompressed bytes in the header
dubbo.rpc.tri.max-header-list-size=8192

等效於 yml 配置

dubbo:
  rpc:
    tri:
      header-table-size: 4096
      enable-push: false
      max-concurrent-streams: 2147483647
      initial-window-size: 1048576
      max-frame-size: 32768
      max-header-list-size: 8192

1.6 屬性和 XML 配置映射規則

xml 標籤名稱和屬性名稱可以組合使用,用“.”分隔。每行一個屬性。

  • dubbo.application.name=foo 等效於 <dubbo:application name="foo" />
  • dubbo.registry.address=10.20.153.10:9090 等效於 <dubbo:registry address="10.20.153.10:9090" />

如果 xml 配置中有多個標籤,則可以使用“id”來區分。如果未指定 id,則將應用於所有標籤。

  • dubbo.protocols.rmi.port=1099 等效於 <dubbo:protocol id="rmi" name="rmi" port="1099" />
  • dubbo.registries.china.address=10.20.153.10:9090 等效於 <dubbo:registry id="china" address="10.20.153.10:9090" />

1.7 配置項的單數和複數比較表

複數配置的命名方式與常規單詞的複數形式相同

  1. 以字母 y 結尾時,去掉 y 並改為 ies
  2. 以字母 s 結尾時,添加 es
  3. 其他情況添加 s

| 配置類型 | 單數配置 | 複數配置 | | ———————————— | ————— ———————————————— | —- ———————————- | | 應用程序 | dubbo.application.xxx=xxx | dubbo.applications.{id}.xxx=xxx
dubbo.applications.{name}.xxx=xxx | | 協議 | dubbo.protocol.xxx=xxx | dubbo.protocols.{id}.xxx=xxx
dubbo.protocols.{name}.xxx=xxx | | 模塊 | dubbo.module.xxx=xxx | dubbo.modules.{id}.xxx=xxx
dubbo.modules.{name}.xxx=xxx | | 註冊中心 | dubbo.registry.xxx=xxx | dubbo.registries.{id}.xxx=xxx | | 監控中心 | dubbo.monitor.xxx=xxx | dubbo.monitors.{id}.xxx=xxx | | 配置中心 | dubbo.config-center.xxx=xxx | dubbo.config-centers.{id}.xxx=xxx | | 元數據中心 | dubbo.metadata-report.xxx=xxx | dubbo.metadata-reports.{id}.xxx=xxx | | ssl | dubbo.ssl.xxx=xxx | dubbo.ssls.{id}.xxx=xxx | | 指標 | dubbo.metrics.xxx=xxx | dubbo.metricses.{id}.xxx=xxx | | 提供者 | dubbo.provider.xxx=xxx | dubbo.providers.{id}.xxx=xxx | | 消費者 | dubbo.consumer.xxx=xxx | dubbo.consumers.{id}.xxx=xxx | | 服務 | dubbo.service.{interfaceName}.xxx=xxx | 無 | | 引用 | dubbo.reference.{interfaceName}.xxx=xxx | 無 | | 方法 | dubbo.service.{interfaceName}.{methodName}.xxx=xxx
dubbo.reference.{interfaceName}.{methodName}.xxx=xxx | 無 | | 參數 | dubbo.service.{interfaceName}.{methodName}.{arg-index}.xxx=xxx | 無 |

2 配置來源

Dubbo 默認支持 6 個配置來源

  • JVM 系統屬性,JVM -D 參數
  • 系統環境變量,JVM 進程的環境變量
  • 外部化配置,[外部化配置] (#33-externalized configuration),從配置中心讀取
  • 應用程序配置,應用程序屬性配置,從 Spring 應用程序環境中提取以“dubbo”開頭的屬性集
  • 通過 API/XML/註解等編程接口收集的配置,可以理解為一種配置來源,是一種直接面向用戶編程的配置收集方式
  • 從類路徑中讀取配置文件 dubbo.properties

關於 dubbo.properties 屬性

  1. 如果 classpath 下有多個 dubbo.properties 文件,例如兩個 jar 包都包含 dubbo.properties,dubbo 會隨機選取一個載入,並印出錯誤日誌。
  2. Dubbo 能自動載入 classpath 根目錄下的 dubbo.properties,但也可以使用 JVM 參數指定路徑:-Ddubbo.properties.file=xxx.properties

2.1 覆蓋關係

如果同一個配置項透過多個配置來源指定,配置項之間會互相覆蓋,具體的覆蓋關係和優先順序請參考下一節。

3. 配置載入流程

3.1 處理流程

Dubbo 配置載入大致分為兩個階段

Configuration loading process

  • 第一階段是在 DubboBootstrap 初始化之前,Spring 上下文啟動時解析處理 XML 配置/註解配置/Java-config 或執行 API 配置程式碼,建立 config bean 並加入到 ConfigManager 中。
  • 第二階段是 DubboBootstrap 初始化流程,會從配置中心讀取外部化配置,依次處理實例級別屬性配置和應用級別屬性配置,最後重新整理所有配置實例的屬性,即[屬性覆蓋](../principle#32-屬性覆蓋)。

3.2 屬性覆蓋

屬性覆蓋發生的場景可能有兩種,兩種可能同時發生

  1. 不同的配置來源配置了相同的配置項
  2. 相同的配置來源,但不同層級指定了相同的配置項

3.2.1 不同的配置來源

Override relationship

3.2.1 相同的配置來源

屬性覆蓋指的是使用配置的屬性值覆蓋 config bean 實例的屬性,類似於 Spring 的 [PropertyOverrideConfigurer](https://spring-docs.dev.org.tw/spring-framework/docs/current/javadoc-api/org/springframework/beans/ factory/config/PropertyOverrideConfigurer.html)。

屬性資源配置器,用於覆蓋應用程式上下文定義中 bean 的屬性值。它將屬性文件中的值推送到 bean 定義中。配置行的預期格式如下

beanName.property=value

但與 PropertyOverrideConfigurer 不同的是,Dubbo 的屬性覆蓋有多種匹配格式,優先順序由高到低為

#1. Instance-level configuration of the specified id
dubbo.{config-type}s.{config-id}.{config-item}={config-item-value}

#2. Specify the instance-level configuration of the name
dubbo.{config-type}s.{config-name}.{config-item}={config-item-value}

#3. Application-level configuration (singular configuration)
dubbo.{config-type}.{config-item}={config-item-value}

屬性覆蓋處理流程

按照優先順序由高到低搜尋,如果找到以此前綴開頭的屬性,則使用此前綴提取屬性,並忽略後續的配置。

Properties Override Process

3.3 外部化配置

外部化配置的目的之一是為了實現配置的集中管理,業界在這一塊已經有很多成熟的專業配置系統,例如 Apollo、Nacos 等,Dubbo 做的主要是保證能夠與這些系統協同工作。

外部化配置與其他本地配置在內容和格式上沒有任何區別,可以簡單理解為 dubbo.properties 的外部化儲存,配置中心更適合提取一些公共配置例如註冊中心、元數據中心配置等用於集中管理。

# Centralized management of registration center address, metadata center address and other configurations can achieve a unified environment and reduce development-side perception.
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.registry.simplified=true

dubbo.metadata-report.address=zookeeper://127.0.0.1:2181

dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

dubbo.application.qos.port=33333
  • 優先順序 預設情況下,外部化配置的優先順序高於本地配置,因此這裡配置的內容會覆蓋本地配置的值。關於各種配置形式之間的[覆蓋關係](#21-覆蓋關係)有單獨的章節說明。

  • 作用域 外部化配置分為全域和應用兩個層級,全域配置所有應用共享,應用級別配置由每個應用自行維護,僅對自身可見。目前支援的擴展實現包括 Zookeeper、Apollo、Nacos。

3.3.1 如何使用外部化配置

  1. 新增 config-center 配置
<dubbo:config-center address="zookeeper://127.0.0.1:2181"/>
  1. 在對應的配置中心(zookeeper、Nacos 等)新增全域配置項,以 Nacos 為例如下

nacos-extenal-properties

啟用外部配置後,理論上應用程式內不再需要配置註冊中心、元數據中心、協議、服務質量(QoS)等全域配置。應用程式開發端只需關注業務服務配置,而一些全域共享的配置則交由維運人員統一在遠端配置中心設定。

如此一來,應用程式只需關心:

  • 服務暴露和訂閱配置
  • 配置中心地址。當部署到不同環境時,其他配置可以從對應的配置中心自動讀取。

例如,每個應用程式中可能只需要以下 Dubbo 相關配置,其餘的都託管在對應環境的配置中心中:

dubbo
  application
    name: demo
  config-center
    address: nacos://127.0.0.1:8848

3.3.2 自行載入外部配置

所謂 Dubbo 支援配置中心,本質上是將 .properties 檔案從遠端拉取到本地,然後與本地配置整合。理論上,只要 Dubbo 框架能取得所需的配置,就能正常啟動。它並不關心這些配置是由自身載入還是由應用程式直接插入,因此 Dubbo 也提供了以下 API,允許使用者自行組織配置並塞入 Dubbo 框架(配置載入過程由使用者自行完成),如此 Dubbo 框架便不再直接與 Apollo 或 Zookeeper 互動讀取配置。

// The application loads its own configuration
Map<String, String> dubboConfigurations = new HashMap<>();
        dubboConfigurations.put("dubbo.registry.address", "zookeeper://127.0.0.1:2181");
        dubboConfigurations.put("dubbo.registry.simplified", "true");

//Throw the organized configuration into the Dubbo framework
        ConfigCenterConfig configCenter = new ConfigCenterConfig();
        configCenter.setExternalConfig(dubboConfigurations);

最後修改日期:2023 年 1 月 2 日:增強英文文件 (#1798) (95a9f4f6c1c)