资讯专栏INFORMATION COLUMN

Dubbo 新编程模型之外部化配置

baihe / 3524人阅读

摘要:同时,所标注的需要被应用上下文注册配置引导类创建配置上下文注册当前配置获取和获取获取运行结果运行后控制台输出输出的内容与绑定的内容一致,符合期望。

Dubbo 外部化配置(Externalized Configuration) 原文地址 外部化配置(Externalized Configuration)

在Dubbo 注解驱动例子中,无论是服务提供方,还是服务消费方,均需要转配相关配置Bean:

    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation-consumer");
        return applicationConfig;
    }

虽然实现类似于ProviderConfigurationConsumerConfiguration 这样的 Spring @Configuration Bean 成本并不高,不过通过 Java Code 的方式定义配置 Bean,或多或少是一种 Hard Code(硬编码)的行为,缺少弹性。

尽管在 Spring 应用中,可以通过 @Value 或者 Environment 的方式获取外部配置,其代码简洁性以及类型转换灵活性存在明显的不足。因此,Spring Boot 提出了外部化配置(External Configuration)的感念,即通过程序以外的配置源,动态地绑定指定类型。

随着 Spring Boot / Spring Cloud 应用的流行,开发人员逐渐地接受并且使用 Spring Boot 外部化配置(External Configuration),即通过 application.properties 或者 bootstrap.properties 装配配置 Bean。

下列表格记录了 Dubbo 内置配置类:

配置类 标签 用途 解释
ProtocolConfig 协议配置 用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受
ApplicationConfig 应用配置 用于配置当前应用信息,不管该应用是提供者还是消费者
ModuleConfig 模块配置 用于配置当前模块信息,可选
RegistryConfig 注册中心配置 用于配置连接注册中心相关信息
MonitorConfig 监控中心配置 用于配置连接监控中心相关信息,可选
ProviderConfig 提供方配置 当 ProtocolConfig 和 ServiceConfig 某属性没有配置时,采用此缺省值,可选
ConsumerConfig 消费方配置 当 ReferenceConfig 某属性没有配置时,采用此缺省值,可选
MethodConfig 方法配置 用于 ServiceConfig 和 ReferenceConfig 指定方法级的配置信息
ArgumentConfig 参数配置 用于指定方法参数配置

通过申明对应的 Spring 扩展标签,在 Spring 应用上下文中将自动生成相应的配置 Bean。

在 Dubbo 官方用户手册的“属性配置”章节中,dubbo.properties 配置属性能够映射到 ApplicationConfigProtocolConfig 以及 RegistryConfig 的字段。从某种意义上来说,dubbo.properties 也是 Dubbo 的外部化配置。

其中,引用“映射规则”的内容:

映射规则

将 XML 配置的标签名,加属性名,用点分隔,多个属性拆成多行

比如:dubbo.application.name=foo等价于

比如:dubbo.registry.address=10.20.153.10:9090等价于

如果 XML 有多行同名标签配置,可用 id 号区分,如果没有 id 号将对所有同名标签生效

比如:dubbo.protocol.rmi.port=1234等价于2

比如:dubbo.registry.china.address=10.20.153.10:9090等价于

下面是 dubbo.properties 的一个典型配置:

dubbo.application.name=foo
dubbo.application.owner=bar
dubbo.registry.address=10.20.153.10:9090

根据“映射规则”,Dubbo 即支持单配置 Bean 映射,也支持多 Bean 映射。综合以上需求,既要兼容 Dubbo 已有的一个或多个 Bean 字段映射绑定,也支持外部化配置。

特别提醒:外部化配置(External Configuration)并非 Spring Boot 特有,即使在 Spring Framework 场景下亦能支持。也就是说 Dubbo 外部化配置即可在 Spring Framework 中工作,也能在 Spring Boot 中运行。

Dubbo 外部化配置(External Configuration) 支持起始版本为:2.5.8

@EnableDubboConfig 起始版本:2.5.8 使用说明
@EnableDubboConfig 定义
public @interface EnableDubboConfig {

    /**
     * It indicates whether binding to multiple Spring Beans.
     *
     * @return the default value is false
     * @revised 2.5.9
     */
    boolean multiple() default false;

}

multiple : 表示是否支持多Dubbo 配置 Bean 绑定。默认值为 false ,即单 Dubbo 配置 Bean 绑定

单 Dubbo 配置 Bean 绑定

为了更好地向下兼容,@EnableDubboConfig 提供外部化配置属性与 Dubbo 配置类之间的绑定,其中映射关系如下:

配置类 外部化配置属性前缀 用途
ProtocolConfig dubbo.protocol 协议配置
ApplicationConfig dubbo.application 应用配置
ModuleConfig dubbo.module 模块配置
RegistryConfig dubbo.registry 注册中心配置
MonitorConfig dubbo.monitor 监控中心配置
ProviderConfig dubbo.provider 提供方配置
ConsumerConfig dubbo.consumer 消费方配置

当标注 @EnableDubboConfig 的类被扫描注册后,同时 Spring(Spring Boot)应用配置(PropertySources)中存在dubbo.application.* 时,ApplicationConfig Bean 将被注册到在 Spring 上下文。否则,不会被注册。如果出现dubbo.registry.*的配置,那么,RegistryConfig Bean 将会创建,以此类推。即按需装配 Dubbo 配置 Bean。

如果需要指定配置 Bean的 id,可通过**.id 属性设置,以dubbo.application 为例:

## application
dubbo.application.id = applicationBean
dubbo.application.name = dubbo-demo-application

以上配置等同于以下 Java Config Bean:

    @Bean("applicationBean")
    public ApplicationConfig applicationBean() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-demo-application");
        return applicationConfig;
    }

大致上配置属性与配置类绑定模式 - dubbo.application.* 映射到 ApplicationConfig 中的字段。

注:当配置属性名称无法在配置类中找到字段时,将会忽略绑定
多 Dubbo 配置 Bean 绑定

Dubbo @Service@Reference 允许 Dubbo 应用关联ApplicationConfig Bean 或者指定多个RegistryConfig Bean 等能力。换句话说,Dubbo 应用上下文中可能存在多个ApplicationConfig 等 Bean定义。

为了适应以上需要,因此从Dubbo 2.5.9 开始,@EnableDubboConfig 支持多 Dubbo 配置 Bean 绑定,同时按照业界规约标准,与单 Dubbo 配置 Bean 绑定约定不同,配置属性前缀均为英文复数形式:

详情请参考 :https://github.com/alibaba/du...

dubbo.applications

dubbo.modules

dubbo.registries

dubbo.protocols

dubbo.monitors

dubbo.providers

dubbo.consumers

dubbo.applications 为例,基本的模式如下:

dubbo.applications.${bean-name}.property-name = ${property-value}

请读者注意,在单 Dubbo 配置 Bean 绑定时,可以通过指定id 属性的方式,定义ApplicationConfig Bean 的ID,即dubbo.application.id

而在多 Dubbo 配置 Bean 绑定时,Bean ID 则由dubbo.applications.与属性字段名称(.property-name)之间的字符来表达。

如下配置:

# multiple Bean definition
dubbo.applications.applicationBean.name = dubbo-demo-application
dubbo.applications.applicationBean2.name = dubbo-demo-application2
dubbo.applications.applicationBean3.name = dubbo-demo-application3

该配置内容中,绑定了三个ApplicationConfig Bean,分别是applicationBeanapplicationBean2以及applicationBean3

示例说明

@EnableDubboConfig 的使用方法很简答, 再次强调一点,当规约的外部配置存在时,相应的 Dubbo 配置类 才会提升为 Spring Bean。简言之,按需装配。

单 Dubbo 配置 Bean 绑定
外部化配置文件

将以下内容的外部化配置文件物理路径为:classpath:/META-INF/config.properties:

# 单 Dubbo 配置 Bean 绑定
## application
dubbo.application.id = applicationBean
dubbo.application.name = dubbo-demo-application

## module
dubbo.module.id = moduleBean
dubbo.module.name = dubbo-demo-module

## registry
dubbo.registry.address = zookeeper://192.168.99.100:32770

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

## monitor
dubbo.monitor.address = zookeeper://127.0.0.1:32770

## provider
dubbo.provider.host = 127.0.0.1

## consumer
dubbo.consumer.client = netty
@EnableDubboConfig 配置 Bean
/**
 * Dubbo 配置 Bean
 *
 * @author Mercy
 */
@EnableDubboConfig
@PropertySource("META-INF/config.properties")
@Configuration
public class DubboConfiguration {

}
实现引导类
/**
 * Dubbo 配置引导类
 *
 * @author Mercy
 */
public class DubboConfigurationBootstrap {

    public static void main(String[] args) {
        // 创建配置上下文
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册当前配置 Bean
        context.register(DubboConfiguration.class);
        context.refresh();
         // application
        ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class);
        System.out.printf("applicationBean.name = %s 
", applicationConfig.getName());

        // module
        ModuleConfig moduleConfig = context.getBean("moduleBean", ModuleConfig.class);
        System.out.printf("moduleBean.name = %s 
", moduleConfig.getName());

        // registry
        RegistryConfig registryConfig = context.getBean(RegistryConfig.class);
        System.out.printf("registryConfig.name = %s 
", registryConfig.getAddress());

        // protocol
        ProtocolConfig protocolConfig = context.getBean(ProtocolConfig.class);
        System.out.printf("protocolConfig.name = %s 
", protocolConfig.getName());
        System.out.printf("protocolConfig.port = %s 
", protocolConfig.getPort());

        // monitor
        MonitorConfig monitorConfig = context.getBean(MonitorConfig.class);
        System.out.printf("monitorConfig.name = %s 
", monitorConfig.getAddress());

        // provider
        ProviderConfig providerConfig = context.getBean(ProviderConfig.class);
        System.out.printf("providerConfig.name = %s 
", providerConfig.getHost());

        // consumer
        ConsumerConfig consumerConfig = context.getBean(ConsumerConfig.class);
        System.out.printf("consumerConfig.name = %s 
", consumerConfig.getClient());
    }
}
执行结果
applicationBean.name = dubbo-demo-application 
moduleBean.name = dubbo-demo-module 
registryConfig.name = zookeeper://192.168.99.100:32770 
protocolConfig.name = dubbo 
protocolConfig.port = 20880 
monitorConfig.name = zookeeper://127.0.0.1:32770 
providerConfig.name = 127.0.0.1 
consumerConfig.name = netty 

不难发现,@EnableDubboConfig 配置 Bean 配合外部化文件 classpath:/META-INF/config.properties,与执行输出内容相同。

多 Dubbo 配置 Bean 绑定
外部化配置文件

将以下内容的外部化配置文件物理路径为:classpath:/META-INF/multiple-config.properties:

# 多 Dubbo 配置 Bean 绑定
## dubbo.applications
dubbo.applications.applicationBean.name = dubbo-demo-application
dubbo.applications.applicationBean2.name = dubbo-demo-application2
dubbo.applications.applicationBean3.name = dubbo-demo-application3
@EnableDubboConfig 配置 Bean(多)
@EnableDubboConfig(multiple = true)
@PropertySource("META-INF/multiple-config.properties")
private static class DubboMultipleConfiguration {

}    
实现引导类
/**
 * Dubbo 配置引导类
 *
 * @author Mercy
 */
public class DubboConfigurationBootstrap {
    public static void main(String[] args) {
        // 创建配置上下文
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册当前配置 Bean
        context.register(DubboMultipleConfiguration.class);
        context.refresh();

        // 获取 ApplicationConfig Bean:"applicationBean"、"applicationBean2" 和 "applicationBean3"
        ApplicationConfig applicationBean = context.getBean("applicationBean", ApplicationConfig.class);
        ApplicationConfig applicationBean2 = context.getBean("applicationBean2", ApplicationConfig.class);
        ApplicationConfig applicationBean3 = context.getBean("applicationBean3", ApplicationConfig.class);

        System.out.printf("applicationBean.name = %s 
", applicationBean.getName());
        System.out.printf("applicationBean2.name = %s 
", applicationBean2.getName());
        System.out.printf("applicationBean3.name = %s 
", applicationBean3.getName());
    }
}
执行结果
applicationBean.name = dubbo-demo-application 
applicationBean2.name = dubbo-demo-application2 
applicationBean3.name = dubbo-demo-application3 

@EnableDubboConfig(multiple = true) 执行后,运行结果说明ApplicationConfig Bean 以及 ID 的定义方式。

@EnableDubboConfigBinding & @EnableDubboConfigBindings

@EnableDubboConfig适合绝大多数外部化配置场景,然而无论是单 Bean 绑定,还是多 Bean 绑定,其外部化配置属性前缀是固化的,如dubbo.application 以及 dubbo.applications

当应用需要自定义外部化配置属性前缀@EnableDubboConfigBinding能提供更大的弹性,支持单个外部化配置属性前缀(prefix) 与 Dubbo 配置 Bean 类型(AbstractConfig 子类)绑定,如果需要多次绑定时,可使用@EnableDubboConfigBindings

尽管 Dubbo 推荐使用 Java 8 ,然而实际的情况,运行时的 JDK 的版本可能从 6到8 均有。因此,@EnableDubboConfigBinding 没有实现java.lang.annotation.Repeatable,即允许实现类不支持重复标注@EnableDubboConfigBinding

@EnableDubboConfigBinding 在支持外部化配置属性与 Dubbo 配置类绑定时,与 Dubbo 过去的映射行为不同,被绑定的 Dubbo 配置类将会提升为 Spring Bean,无需提前装配 Dubbo 配置类。同时,支持多 Dubbo 配置Bean 装配。其 Bean 的绑定规则与@EnableDubboConfig一致。

起始版本: 2.5.8 使用说明
@EnableDubboConfigBinding 定义
public @interface EnableDubboConfigBinding {

    /**
     * The name prefix of the properties that are valid to bind to {@link AbstractConfig Dubbo Config}.
     *
     * @return the name prefix of the properties to bind
     */
    String prefix();

    /**
     * @return The binding type of {@link AbstractConfig Dubbo Config}.
     * @see AbstractConfig
     * @see ApplicationConfig
     * @see ModuleConfig
     * @see RegistryConfig
     */
    Class type();

    /**
     * It indicates whether {@link #prefix()} binding to multiple Spring Beans.
     *
     * @return the default value is false
     */
    boolean multiple() default false;

}

prefix() : 指定待绑定 Dubbo 配置类的外部化配置属性的前缀,比如dubbo.applicationApplicationConfig 的外部化配置属性的前缀。prefix() 支持占位符(Placeholder), 并且其关联前缀值是否以"." 作为结尾字符是可选的,即prefix() = "dubbo.application"prefix() = "dubbo.application." 效果相同

type() : 指定 Dubbo 配置类,所有 AbstractConfig 的实现子类即可,如ApplicationConfigRegistryConfig 以及 ProtocolConfig

multiple() : 表明是否需要将prefix() 作为多个 type() 类型的 Spring Bean 外部化配置属性。默认值为false,即默认支持单个类型的 Spring 配置 Bean

假设标注 @EnableDubboConfigBinding 的实现类被 Spring 应用上下文扫描并且注册后,其中prefix() = dubbo.apptype() = ApplicationConfig.class ,且外部配置内容为:

dubbo.app.id = applicationBean
dubbo.app.name = dubbo-demo-application

Spring 应用上下文启动后,一个 ID 为 "applicationBean" 的 ApplicationConfig Bean 被初始化,其 name 字段被设置为 "dubbo-demo-application"。

EnableDubboConfigBindings 定义
public @interface EnableDubboConfigBindings {

    /**
     * The value of {@link EnableDubboConfigBindings}
     *
     * @return non-null
     */
    EnableDubboConfigBinding[] value();

}

value : 指定多个EnableDubboConfigBinding,用于实现外部化配置属性前缀(prefix) 与 Dubbo 配置 Bean 类型(AbstractConfig 子类)绑定。

示例说明
外部化配置文件

将以下内容的外部化配置文件物理路径为:classpath:/META-INF/bindings.properties

# classpath:/META-INF/bindings.properties
## 占位符值 : ApplicationConfig 外部配置属性前缀
applications.prefix = dubbo.apps.

## 多 ApplicationConfig Bean 绑定
dubbo.apps.applicationBean.name = dubbo-demo-application
dubbo.apps.applicationBean2.name = dubbo-demo-application2
dubbo.apps.applicationBean3.name = dubbo-demo-application3

## 单 ModuleConfig Bean 绑定
dubbo.module.id = moduleBean
dubbo.module.name = dubbo-demo-module

## 单 RegistryConfig Bean 绑定
dubbo.registry.address = zookeeper://192.168.99.100:32770
EnableDubboConfigBindings 配置 Bean

DubboConfiguration 作为 Dubbo 配置 Bean,除通过 @EnableDubboConfigBinding 绑定之外,还需要 @PropertySource 指定外部化配置文件(classpath:/META-INF/bindings.properties):

/**
 * Dubbo 配置 Bean
 *
 * @author Mercy
 */
@EnableDubboConfigBindings({
        @EnableDubboConfigBinding(prefix = "${applications.prefix}",
                type = ApplicationConfig.class, multiple = true), // 多 ApplicationConfig Bean 绑定
        @EnableDubboConfigBinding(prefix = "dubbo.module", // 不带 "." 后缀
                type = ModuleConfig.class), // 单 ModuleConfig Bean 绑定
        @EnableDubboConfigBinding(prefix = "dubbo.registry.", // 带 "." 后缀
                type = RegistryConfig.class) // 单 RegistryConfig Bean 绑定
})
@PropertySource("META-INF/bindings.properties")
@Configuration
public class DubboConfiguration {
  
}
实现引导类

通过之前的使用说明,当 EnableDubboConfigBinding 将外部配置化文件classpath:/META-INF/dubbo.properties 绑定到 ApplicationConfig后,其中 Spring Bean "applicationBean" 的 name 字段被设置成 "dubbo-demo-application"。同时, EnableDubboConfigBinding 所标注的 DubboConfiguration 需要被 Sring 应用上下文注册:

/**
 * Dubbo 配置引导类
 *
 * @author Mercy
 */
public class DubboConfigurationBootstrap {

    public static void main(String[] args) {
        // 创建配置上下文
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册当前配置 Bean
        context.register(DubboConfiguration.class);
        context.refresh();
         // 获取 ApplicationConfig Bean:"applicationBean"、"applicationBean2" 和 "applicationBean3"
        ApplicationConfig applicationBean = context.getBean("applicationBean", ApplicationConfig.class);
        ApplicationConfig applicationBean2 = context.getBean("applicationBean2", ApplicationConfig.class);
        ApplicationConfig applicationBean3 = context.getBean("applicationBean3", ApplicationConfig.class);

        System.out.printf("applicationBean.name = %s 
", applicationBean.getName());
        System.out.printf("applicationBean2.name = %s 
", applicationBean2.getName());
        System.out.printf("applicationBean3.name = %s 
", applicationBean3.getName());

        // 获取 ModuleConfig Bean:"moduleBean"
        ModuleConfig moduleBean = context.getBean("moduleBean", ModuleConfig.class);

        System.out.printf("moduleBean.name = %s 
", moduleBean.getName());

        // 获取 RegistryConfig Bean
        RegistryConfig registry = context.getBean(RegistryConfig.class);

        System.out.printf("registry.address = %s 
", registry.getAddress());
    }
}
运行结果

DubboConfigurationBootstrap 运行后控制台输出:

applicationBean.name = dubbo-demo-application 
applicationBean2.name = dubbo-demo-application2 
applicationBean3.name = dubbo-demo-application3 
moduleBean.name = dubbo-demo-module 
registry.address = zookeeper://192.168.99.100:32770 

输出的内容与classpath:/META-INF/bindings.properties 绑定的内容一致,符合期望。

下篇预告 《Dubbo 微服务编程模型》
更多 Dubbo 以及 微服务相关内容,请关注小马哥公众号:
关于作者

小马哥,十余年Java EE 从业经验,架构师、微服务布道师、Dubbo 维护者。目前主要负责阿里巴巴集团微服务技术实施、架构衍进、基础设施构建等。重点关注云计算、微服务以及软件架构等领域。通过SUN Java(SCJP、SCWCD、SCBCD)以及Oracle OCA 等的认证。

github:https://github.com/mercyblitz sf.gg : https://segmentfault.com/u/me... 微信/微博:mercyblitz

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68121.html

相关文章

  • Dubbo 新编模型注解驱动

    摘要:在生态系统中,以和为代表的微服务框架,引入了全新的编程模型,包括注解驱动外部化配置以及自动装配等。新的编程模型无需配置简化部署提升开发效率。同时,新的编程模型也是即将发布的的基础设施。 原文地址 整体愿景 随着微服务架构的广泛地推广和实施。在 Java 生态系统中,以 Spring Boot 和 Spring Cloud 为代表的微服务框架,引入了全新的编程模型,包括注解驱动(Anno...

    chavesgu 评论0 收藏0
  • 官方 Dubbo Spring Boot Starter 1.0.0 公测版

    摘要:公告今天小马哥非常高兴地向各位小伙伴宣布,官方公测版已开发完毕,即将发布至公有仓库,目前正在内部测试中。为了收集更多的用户反馈,小马哥诚邀大家一同参与使用测试以及共同维护,项目工程地址如果您喜爱并想了解工程的动态,不妨点击按钮加以关注。 公告 今天小马哥非常高兴地向各位小伙伴宣布,官方 Dubbo Spring Boot Starter 1.0.0 公测版已开发完毕,即将发布至 Mav...

    MrZONT 评论0 收藏0
  • Dubbo Spring Cloud 重塑微服务治理

    摘要:在服务治理方面,相较于而言,并不成熟。遗憾的是,往往被部分开发者片面地视作服务治理的框架,而非微服务基础设施。因此,建议开发人员将或者迁移为服务。因此,下一步需要将其配置服务远程。当服务提供方启动后,下一步实现一个服务消费方。 原文链接:Dubbo Spring Cloud 重塑微服务治理,来自于微信公众号:次灵均阁 摘要 在 Java 微服务生态中,Spring Cloud1 成为...

    wh469012917 评论0 收藏0
  • dubbo源码解析(四十三)2.7新特性

    摘要:大揭秘目标了解的新特性,以及版本升级的引导。四元数据改造我们知道以前的版本只有注册中心,注册中心的有数十个的键值对,包含了一个服务所有的元数据。 DUBBO——2.7大揭秘 目标:了解2.7的新特性,以及版本升级的引导。 前言 我们知道Dubbo在2011年开源,停止更新了一段时间。在2017 年 9 月 7 日,Dubbo 悄悄的在 GitHub 发布了 2.5.4 版本。随后,版本...

    qqlcbb 评论0 收藏0
  • Dubbo Cloud Native 实践与思考

    摘要:可简单地认为它是的扩展,负载均衡自然成为不可或缺的特性。类似的特性在项目也有体现,它是另一种高性能代理的方案,提供服务发现健康和负载均衡。 Dubbo Cloud Native 实践与思考 分享简介 Cloud Native 应用架构随着云技术的发展受到业界特别重视和关注,尤其是 CNCF(Cloud Native Computing Foundation)项目蓬勃发展之际。Dubbo...

    邱勇 评论0 收藏0

发表评论

0条评论

baihe

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<