apache / dubbo

The java implementation of Apache Dubbo. An RPC and microservice framework.
https://dubbo.apache.org/
Apache License 2.0
40.55k stars 26.44k forks source link

Dubbo 3 属性配置说明 #7890

Open kylixs opened 3 years ago

kylixs commented 3 years ago

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

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

属性配置覆盖

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

#格式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}

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

@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的作用。 下面是配置样例:

# 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

多实例的配置样例:

#多个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的配置格式有所不同,按照下面的格式:

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

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

如DemoService接口的配置:

# 服务接口配置
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。

案例分析

为了更透彻理解属性配置覆盖的功能,下面用几个例子进行分析说明。 下面几个例子都使用一份属性配置:

# 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)

DubboBootstrap.getInstance()
    ...
    .protocol(new ProtocolConfig())
    ...

这里添加了一个空白的ProtocolConfig实例,没有设置id和name,根据上面的配置格式优先级,只能使用配置格式3(单数配置),如 dubbo.protocol.xxx=xxx

#default protocol config 
dubbo.protocol.name=dubbo
dubbo.protocol.port=20883

例子2(Spring XML):

<dubbo:protocol name="dubbo" port="20813"/>

这里通过XML定义了一个Protocol,并指定了name="dubbo",刚好匹配上配置格式2(带name的配置)。

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

例子3(Spring Java-config):

@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)。

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

例子4:

@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]

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

例子5:

<dubbo:protocol name="rest" port="8080"/>

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

#default protocol config 
dubbo.protocol.name=dubbo
dubbo.protocol.port=20883
CrazyHZM commented 3 years ago

After Dubbo3.0, we need to provide a more comprehensive configuration description. https://github.com/apache/dubbo-website/issues/970