apache / apache/dubbo

Dubbo 3 属性配置说明

Open
#7,890 1 comment 3 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
41.6k
Forks
26.4k
Avg merge
15h 13m
Merged PRs (30d)
4

Description

在Dubbo 2中,属性配置与dubbo-spring-boot外部化配置的功能存在重叠,规则不清晰,在API配置、Spring XML配置、Java-config配置等不同场景下存在比较多的问题。

Dubbo 3对属性配置进行重新梳理,明确属性配置覆盖的规则,并融合外部化配置功能,贯通API配置、Spring XML配置、Java-config配置等不同场景。

### 属性配置覆盖
属性配置覆盖是指用配置属性值覆盖config实例的字段值,类似Spring `PropertyOverrideConfigurer`的作用。
属性配置格式优先级(由高到低)如下:

```bash
#格式1 指定实例id的属性配置:复数前缀+config-id
dubbo.{config-type}s.{config-id}.{config-item}={config-item-value}

#格式2 指定实例name的属性配置:复数前缀+config-name (没有name属性时忽略此项)
dubbo.{config-type}s.{config-name}.{config-item}={config-item-value}

#格式3 单数配置(匿名实例配置):单数前缀
dubbo.{config-type}.{config-item}={config-item-value}

```
属性覆盖时,依照上面的次序查找匹配的属性,如果存在该种格式的属性,则选定此前缀来提取属性集合,其它的格式的配置将被忽略。举例说明:

```java
@Configuration
public class DubboConfig {

@Bean
public ProtocolConfig protocolConfig(){
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setId("my-protocol");
protocolConfig.setName("dubbo");
return protocolConfig;
}
}

```
上面的ProtocolConfig属性覆盖查找顺序:

(1) 其id为"my-protocol", 尝试查找带id的配置: dubbo.protocols.my-protocol.xxx=xxx

(2) 如果没有找到匹配的属性配置,则继续找带name的配置(其name为"dubbo"):dubbo.protocols.dubbo.xxx=xxx

(3) 如果没有找到匹配的属性配置,则继续找单数配置:dubbo.protocol.xxx=xxx

> 注意: 按优先级高到低查找属性配置,如果找到匹配的属性配置,则使用此前缀打头的一组属性,不会再使用后面的格式。可以参照SpringBoot ConfigurationProperties的prefix来理解,不同的是Dubbo属性配置的prefix不是固定的,而是从多个prefix中选择存在的最高优先级的prefix。

### 外部化配置
外部化配置是指将DubboBootstrap API/Spring XML/Java-config等方式的config配置改为通过属性配置,即从配置属性生成config实例,类似SpringBoot ConfigurationProperties的作用。
下面是配置样例:

```bash
# application
dubbo.application.name=demoapp

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

# registry
dubbo.registry.address=zookeeper://10.10.10.1:2181

# config-center
dubbo.config-center.address=zookeeper://10.10.10.2:2181

# consumer
dubbo.consumer.check=false

```
多实例的配置样例:

```bash
#多个registry
dubbo.registries.register1.address=zookeeper://10.10.10.1:2181
dubbo.registries.register2.address=zookeeper://10.10.10.2:2181

#多个protocol
dubbo.protocols.dubbo.port=20881
dubbo.protocols.rest.port=8080

```
> 注意:Dubbo 3在内核支持了外部化配置功能,在非SpringBoot环境也可以正常使用。

**属性配置覆盖 VS 外部化配置:**
(1) 外部化配置创建config实例时会检查是否存在相同id的config实例,如果不存在则创建,否则按照属性配置覆盖逻辑刷新原config实例的值;
(2) 只有不存在某种类型的config实例时,才会根据单数配置创建config实例。


### 服务接口的配置
service 和reference的配置格式有所不同,按照下面的格式:

```bash
# 服务接口配置
dubbo.service.{interfaceName}.{item}={value}
dubbo.reference.{interfaceName}.{item}={value}

# 接口的方法配置
dubbo.service.{interfaceName}.{methodName}.{item}={value}
dubbo.reference.{interfaceName}.{methodName}.{item}={value}
```
如DemoService接口的配置:

```bash
# 服务接口配置
dubbo.service.org.apache.dubbo.demo.DemoService.timeout=500
dubbo.reference.org.apache.dubbo.demo.DemoService.check=false

# 接口的方法配置
dubbo.service.org.apache.dubbo.demo.DemoService.sayHello.timeout=500
dubbo.reference.org.apache.dubbo.demo.DemoService.sayHello.retries=3
```

### 单复数配置对照表
复数配置的命名与普通单词变复数的规则相同:
(1) 字母y结尾时,去掉y,改为ies
(2) 字母s结尾时,加es
(3) 其它加s

| Config Type | 单数配置 | 复数配置 |
| --- | --- | --- |
| application | dubbo.application.xxx=xxx | dubbo.applications.{id}.xxx=xxx
dubbo.applications.{name}.xxx=xxx |
| protocol | dubbo.protocol.xxx=xxx | dubbo.protocols.{id}.xxx=xxx
dubbo.protocols.{name}.xxx=xxx |
| module | dubbo.module.xxx=xxx | dubbo.modules.{id}.xxx=xxx
dubbo.modules.{name}.xxx=xxx |
| registry | dubbo.registry.xxx=xxx | dubbo.registries.{id}.xxx=xxx |
| monitor | dubbo.monitor.xxx=xxx | dubbo.monitors.{id}.xxx=xxx |
| config-center | dubbo.config-center.xxx=xxx | dubbo.config-centers.{id}.xxx=xxx |
| metadata-report | dubbo.metadata-report.xxx=xxx | dubbo.metadata-reports.{id}.xxx=xxx |
| ssl | dubbo.ssl.xxx=xxx | dubbo.ssls.{id}.xxx=xxx |
| metrics | dubbo.metrics.xxx=xxx | dubbo.metricses.{id}.xxx=xxx |
| provider | dubbo.provider.xxx=xxx | dubbo.providers.{id}.xxx=xxx |
| consumer | dubbo.consumer.xxx=xxx | dubbo.consumers.{id}.xxx=xxx |
| service | dubbo.service.{interfaceName}.xxx=xxx | 无 |
| reference | dubbo.reference.{interfaceName}.xxx=xxx | 无 |
| method | dubbo.service.{interfaceName}.{methodName}.xxx=xxx
dubbo.reference.{interfaceName}.{methodName}.xxx=xxx | 无 |
| argument| dubbo.service.{interfaceName}.{methodName}.{arg-index}.xxx=xxx |无|

> 注意:service/reference的配置格式与其它不一样,为单数前缀+接口名。

#### 忽略的字段
Config的一些字段是内部使用,不能被配置的属性覆盖,刷新属性时会被忽略掉。
如:refreshed、valid、inited、prefixes、parentPrefix等,详细列表请查看org.apache.dubbo.config.AbstractConfig#IGNORED_ATTRIBUTES。

### 案例分析
为了更透彻理解属性配置覆盖的功能,下面用几个例子进行分析说明。
下面几个例子都使用一份属性配置:
```bash
# default protocol config
dubbo.protocol.name=dubbo
dubbo.protocol.port=20883

# protocol config of name=dubbo
dubbo.protocols.dubbo.port=20881

# protocol config of id=my-protocol
dubbo.protocols.my-protocol.name=dubbo
dubbo.protocols.my-protocol.port=20881
```

**例子1(DubboBootstrap API)**:
```java
DubboBootstrap.getInstance()
...
.protocol(new ProtocolConfig())
...
```
这里添加了一个空白的ProtocolConfig实例,没有设置id和name,根据上面的配置格式优先级,只能使用配置格式3(单数配置),如 `dubbo.protocol.xxx=xxx` 。
```bash
#default protocol config
dubbo.protocol.name=dubbo
dubbo.protocol.port=20883
```

**例子2(Spring XML):**
```xml

```
这里通过XML定义了一个Protocol,并指定了name="dubbo",刚好匹配上配置格式2(带name的配置)。
```bash
# protocol config of name=dubbo
dubbo.protocols.dubbo.port=20881

```

**例子3(Spring Java-config):**
```java
@Configuration
public class DubboConfig {

@Bean("my-protocol")
public ProtocolConfig protocolConfig(){
return new ProtocolConfig();
}
}
```
这里定义了一个ProtocolConfig 的bean,没有在代码中指定id。当config id为空时,Dubbo会在BeanPostProcessor中将beanName设置为config实例的id。 根据上面的配置格式优先级,会优匹配带id的配置属性(dubbo.protocols.my-protocol.xxx=xxx)。
```bash
# protocol config of id=my-protocol
dubbo.protocols.my-protocol.name=dubbo
dubbo.protocols.my-protocol.port=20881
```

**例子4:**
```java
@Configuration
public class DubboConfig {

@Bean
public ProtocolConfig protocolConfig(){
return new ProtocolConfig("dubbo");
}
}
```
这个例子与例子3的区别是ProtocolConfig的beanName为protocolConfig,会将其设置为ProtocolConfig的id。另外一个区别是设置是协议名称为"dubbo"。
属性查找过程:
1)尝试查找带id的属性:dubbo.protocols.protocolConfig.xxx=xxx,但没有找到这类属性;
2)尝试查找带name的属性:dubbo.protocols.dubbo.xxx=xxx,匹配上了第2组配置[protocol config of name=dubbo]
```bash
# protocol config of name=dubbo
dubbo.protocols.dubbo.port=20881
```

**例子5:**
```xml

```
属性查找过程:
1)这个例子的protocol指定name,但没有id(自动生成的beanName不会设置为config id,不会用于属性匹配);
2)查找带name的属性配置: dubbo.protocols.rest.xxx=xxx,但没有找到这种属性;
3)最后查找单数属性配置:dubbo.protocol.xxx=xxx
```bash
#default protocol config
dubbo.protocol.name=dubbo
dubbo.protocol.port=20883
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.