Spring Cloud Alibaba,分布式配置(二)(下)

简介: Spring Cloud Alibaba,分布式配置(二)

5.3 使用 Nacos Config 监听实现 Bean 属性动态刷新

前文曾提及 com.alibaba.nacos.api.config.listener.Listener是 Nacos Client API 标准的配置监听器接口,由于仅监听配置内容,并不能直接与 Spring 体系打通,因此,需要借助于 Spring Cloud Alibaba Nacos Config API NacosConfigManager(感谢小伙伴 liaochuntao 和 zkzlx 的代码贡献),代码调整如下:

@SpringBootApplication
@RestController
@RefreshScope
@EnableConfigurationProperties(User.class)
public class NacosConfigSampleApplication {
    @Value("${user.name}")
    private String userName;
    @Value("${user.age}")
    private int userAge;
    @Autowired
    private User user;
    @Autowired
    private NacosConfigManager nacosConfigManager;
    @Bean
    public ApplicationRunner runner() {
        return args -> {
            String dataId = "nacos-config-sample.properties";
            String group = "DEFAULT_GROUP";
            nacosConfigManager.getConfigService().addListener(dataId, group, new AbstractListener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    System.out.println("[Listener] " + configInfo);
                }
            });
        };
    }
    @PostConstruct
    public void init() {
        System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
    }
    @PreDestroy
    public void destroy() {
        System.out.printf("[destroy] user name : %s , age : %d%n", userName, userAge);
    }
    @RequestMapping("/user")
    public String user() {
        return "[HTTP] " + user;
    }
    public static void main(String[] args) {
        SpringApplication.run(NacosConfigSampleApplication.class, args);
    }
}

代码主要变化:

  • @Autowired依赖注入 NacosConfigManager
  • 新增 runner()方法,通过 NacosConfigManagerBean 获取 ConfigService,并增加了 AbstractListener( Listener抽象类)实现,监听 dataId = “nacos-config-sample.properties” 和 group = “DEFAULT_GROUP” 的配置内容

重启应用,并将配置 user.age 从 19 调整到 90,观察日志变化:

c.a.n.client.config.impl.ClientWorker    : [fixed-127.0.0.1_8848] [data-received] dataId=nacos-config-sample.properties, group=DEFAULT_GROUP, tenant=null, md5=b0f42fac52934faf69757c2b6770d39c, content=user.name=nacos-config-sample
user.age=90, type=properties
[Listener] user.name=nacos-config-sample
user.age=90
......

在第 1 行日志下方,新增了监听实现代码的输出内容,不过这段内容是完整的配置,而非变化的内容。读者请务必注意其中的差异。下一步要解决的是将配置映射到 Bean 属性,此处给出一个简单的解决方案,实现步骤有两个:

  • 将 String 内容转化为 Properties 对象
  • 将 Properties 属性值设置到对应的 Bean 属性

代码调整如下:

@SpringBootApplication
@RestController
@RefreshScope
@EnableConfigurationProperties(User.class)
public class NacosConfigSampleApplication {
    ......
    @Bean
    public ApplicationRunner runner() {
        return args -> {
            String dataId = "nacos-config-sample.properties";
            String group = "DEFAULT_GROUP";
            nacosConfigManager.getConfigService().addListener(dataId, group, new AbstractListener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    System.out.println("[Listener] " + configInfo);
                    System.out.println("[Before User] " + user);
                    Properties properties = new Properties();
                    try {
                        properties.load(new StringReader(configInfo));
                        String name = properties.getProperty("user.name");
                        int age = Integer.valueOf(properties.getProperty("user.age"));
                        user.setName(name);
                        user.setAge(age);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    System.out.println("[After User] " + user);
                }
            });
        };
    }
    ......
}

重启应用,并将配置 user.age 从 90 调整到 19,观察日志变化:

[Listener] user.name=nacos-config-sample
user.age= 19
[Before User] User{name='nacos-config-sample', age=90}
[After User] User{name='nacos-config-sample', age=19}

上述三个例子均围绕着 Nacos Config 实现 Bean 属性动态更新,不过它们是 Spring Cloud 使用场景。如果读者的应用仅使用 Spring 或者 Spring Boot,可以考虑 Nacos Spring 工程, Github 地址:https://github.com/nacos-group/nacos-spring-project,其中 @NacosValue支持属性粒度的更新。

6. Nacos Config 高级配置

6.1 支持自定义 namespace 的配置

首先看一下 Nacos 的 Namespace 的概念, Nacos 概念

用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

在没有明确指定 ${spring.cloud.nacos.config.namespace}配置的情况下, 默认使用的是 Nacos 上 Public 这个namespae。如果需要使用自定义的命名空间,可以通过以下配置来实现:

spring.cloud.nacos.config.namespace=b3404bc0-d7dc-4855-b519-570ed34b62d7

注:该配置必须放在 bootstrap.properties 文件中。此外 spring.cloud.nacos.config.namespace的值是 namespace 对应的 id,id 值可以在 Nacos 的控制台获取。并且在添加配置时注意不要选择其他的 namespae,否则将会导致读取不到正确的配置

6.2 支持自定义 Group 的配置

在没有明确指定 ${spring.cloud.nacos.config.group}配置的情况下, 默认使用的是 DEFAULT_GROUP 。如果需要自定义自己的 Group,可以通过以下配置来实现:

spring.cloud.nacos.config.group=DEVELOP_GROUP

注:该配置必须放在 bootstrap.properties 文件中。并且在添加配置时 Group 的值一定要和 spring.cloud.nacos.config.group的配置值一致。

6.3 支持自定义扩展的 Data Id 配置

Spring Cloud Alibaba Nacos Config 从 0.2.1 版本后,可支持自定义 Data Id 的配置。关于这部分详细的设计可参考 这里。一个完整的配置案例如下所示:

spring.application.name=opensource-service-provider
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# config external configuration
# 1、Data Id 在默认的组 DEFAULT_GROUP,不支持配置的动态刷新
spring.cloud.nacos.config.extension-configs[0].data-id=ext-config-common01.properties
# 2、Data Id 不在默认的组,不支持动态刷新
spring.cloud.nacos.config.extension-configs[1].data-id=ext-config-common02.properties
spring.cloud.nacos.config.extension-configs[1].group=GLOBALE_GROUP
# 3、Data Id 既不在默认的组,也支持动态刷新
spring.cloud.nacos.config.extension-configs[2].data-id=ext-config-common03.properties
spring.cloud.nacos.config.extension-configs[2].group=REFRESH_GROUP
spring.cloud.nacos.config.extension-configs[2].refresh=true

可以看到:

  • 通过 spring.cloud.nacos.config.extension-configs[n].data-id的配置方式来支持多个 Data Id 的配置。
  • 通过 spring.cloud.nacos.config.extension-configs[n].group的配置方式自定义 Data Id 所在的组,不明确配置的话,默认是 DEFAULT_GROUP。
  • 通过 spring.cloud.nacos.config.extension-configs[n].refresh的配置方式来控制该 Data Id 在配置变更时,是否支持应用中可动态刷新, 感知到最新的配置值。默认是不支持的。

注:多个 Data Id 同时配置时,他的优先级关系是 spring.cloud.nacos.config.extension-configs[n].data-id其中 n 的值越大,优先级越高。

spring.cloud.nacos.config.extension-configs[n].data-id的值必须带文件扩展名,文件扩展名既可支持 properties,又可以支持 yaml/yml。此时 spring.cloud.nacos.config.file-extension的配置对自定义扩展配置的 Data Id 文件扩展名没有影响。

通过自定义扩展的 Data Id 配置,既可以解决多个应用间配置共享的问题,又可以支持一个应用有多个配置文件。

为了更加清晰的在多个应用间配置共享的 Data Id ,你可以通过以下的方式来配置:

# 配置支持共享的 Data Id
spring.cloud.nacos.config.shared-configs[0].data-id=common.yaml
# 配置 Data Id 所在分组,缺省默认 DEFAULT_GROUP
spring.cloud.nacos.config.shared-configs[0].group=GROUP_APP1
# 配置Data Id 在配置变更时,是否动态刷新,缺省默认 false
spring.cloud.nacos.config.shared-configs[0].refresh=true

可以看到:

  • 通过 spring.cloud.nacos.config.shared-configs[n].data-id来支持多个共享 Data Id 的配置。
  • 通过 spring.cloud.nacos.config.shared-configs[n].group来配置自定义 Data Id 所在的组,不明确配置的话,默认是 DEFAULT_GROUP。
  • 通过 spring.cloud.nacos.config.shared-configs[n].refresh来控制该Data Id在配置变更时,是否支持应用中动态刷新,默认false。

6.4 配置的优先级

Spring Cloud Alibaba Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置。

  • A: 通过 spring.cloud.nacos.config.shared-configs[n].data-id支持多个共享 Data Id 的配置
  • B: 通过 spring.cloud.nacos.config.extension-configs[n].data-id的方式支持多个扩展 Data Id 的配置
  • C: 通过内部相关规则(应用名、应用名+ Profile )自动生成相关的 Data Id 配置

当三种方式共同使用时,他们的一个优先级关系是:A < B < C

6.5 完全关闭配置

通过设置 spring.cloud.nacos.config.enabled = false 来完全关闭 Spring Cloud Nacos Config

6.6 更多高级配置

更多关于 Nacos Config Starter 的配置项如下所示:

配置项 Key 默认值 说明
服务端地址 spring.cloud.nacos.config.server-addr
Nacos Server 启动监听的ip地址和端口
配置对应的 DataId spring.cloud.nacos.config.name
先取 prefix,再取 name,最后取 spring.application.name
配置对应的 DataId spring.cloud.nacos.config.prefix
先取 prefix,再取 name,最后取 spring.application.name
配置内容编码 spring.cloud.nacos.config.encode
读取的配置内容对应的编码
GROUP spring.cloud.nacos.config.group DEFAULT_GROUP 配置对应的组
文件扩展名 spring.cloud.nacos.config.fileExtension properties 配置项对应的文件扩展名,目前支持 properties 和 yaml(yml)
获取配置超时时间 spring.cloud.nacos.config.timeout 3000 客户端获取配置的超时时间(毫秒)
接入点 spring.cloud.nacos.config.endpoint
地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
命名空间 spring.cloud.nacos.config.namespace
常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等
AccessKey spring.cloud.nacos.config.accessKey
当要上阿里云时,阿里云上面的一个云账号名
SecretKey spring.cloud.nacos.config.secretKey
当要上阿里云时,阿里云上面的一个云账号密码
Nacos Server 对应的 context path spring.cloud.nacos.config.contextPath
Nacos Server 对外暴露的 context path
集群 spring.cloud.nacos.config.clusterName
配置成Nacos集群名称
共享配置 spring.cloud.nacos.config.sharedDataids
共享配置的 DataId, “,” 分割
共享配置动态刷新 spring.cloud.nacos.config.refreshableDataids
共享配置中需要动态刷新的 DataId, “,” 分割
自定义 Data Id 配置 spring.cloud.nacos.config.extConfig
属性是个集合,内部由 ConfigPOJO 组成。Config有 3 个属性,分别是 dataIdgroup以及 refresh

7. Nacos Config Actuator Endpoint

Nacos Config 内部提供了一个 Endpoint, 对应的 Endpoint ID 为 nacos-config,其 Actuator Web Endpoint URI 为 /actuator/nacos-config

注:使用 Nacos Config Spring Cloud 1.x 版本的话,其 URI 地址则为 /nacos-config

其中,Endpoint 暴露的 json 中包含了三种属性:

  • NacosConfigProperties: 当前应用 Nacos 的基础配置信息
  • RefreshHistory: 配置刷新的历史记录
  • Sources: 当前应用配置的数据信息

由于 Aliyun Java Initializr 所生成的应用工程默认激活 Spring Boot Actuator Endpoints(JMX 和 Web),具体配置存放在 application.properties文件中,同时,Actuator Web 端口设置为 8081,内容如下:

management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
# Actuator Web 访问端口
management.server.port=8081

因此,应用 nacos-config-sample 无需调整,直接访问:http://127.0.0.1:8081/actuator/nacos-config,服务响应的内容如下:

{
  "NacosConfigProperties": {
    "serverAddr": "127.0.0.1:8848",
    "username": "",
    "password": "",
    "encode": null,
    "group": "DEFAULT_GROUP",
    "prefix": null,
    "fileExtension": "properties",
    "timeout": 3000,
    "maxRetry": null,
    "configLongPollTimeout": null,
    "configRetryTime": null,
    "enableRemoteSyncConfig": false,
    "endpoint": null,
    "namespace": null,
    "accessKey": null,
    "secretKey": null,
    "contextPath": null,
    "clusterName": null,
    "name": null,
    "sharedConfigs": null,
    "extensionConfigs": null,
    "refreshEnabled": true,
    "sharedDataids": null,
    "refreshableDataids": null,
    "extConfig": null,
    "configServiceProperties": {
      "secretKey": "",
      "namespace": "",
      "username": "",
      "enableRemoteSyncConfig": "false",
      "configLongPollTimeout": "",
      "configRetryTime": "",
      "encode": "",
      "serverAddr": "127.0.0.1:8848",
      "maxRetry": "",
      "clusterName": "",
      "password": "",
      "accessKey": "",
      "endpoint": ""
    }
  },
  "RefreshHistory": [
  ],
  "Sources": [
    {
      "lastSynced": "2020-09-14 11:11:37",
      "dataId": "nacos-config-sample.properties"
    },
    {
      "lastSynced": "2020-09-14 11:11:37",
      "dataId": "nacos-config-sample"
    }
  ]
}
目录
相关文章
|
7月前
|
人工智能 Java Nacos
基于 Spring AI Alibaba + Nacos 的分布式 Multi-Agent 构建指南
本文将针对 Spring AI Alibaba + Nacos 的分布式多智能体构建方案展开介绍,同时结合 Demo 说明快速开发方法与实际效果。
5116 99
|
7月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
7765 109
|
8月前
|
机器学习/深度学习 监控 算法
分布式光伏储能系统的优化配置方法(Matlab代码实现)
分布式光伏储能系统的优化配置方法(Matlab代码实现)
475 1
|
8月前
|
人工智能 Java 机器人
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
Spring AI Alibaba集成Ollama,基于Java构建本地大模型应用,支持流式对话、knife4j接口可视化,实现高隐私、免API密钥的离线AI服务。
6956 2
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
|
7月前
|
编解码 运维 算法
【分布式能源选址与定容】光伏、储能双层优化配置接入配电网研究(Matlab代码实现)
【分布式能源选址与定容】光伏、储能双层优化配置接入配电网研究(Matlab代码实现)
641 12
|
7月前
|
人工智能 监控 Java
Spring AI Alibaba实践|后台定时Agent
基于Spring AI Alibaba框架,可构建自主运行的AI Agent,突破传统Chat模式限制,支持定时任务、事件响应与人工协同,实现数据采集、分析到决策的自动化闭环,提升企业智能化效率。
Spring AI Alibaba实践|后台定时Agent
|
9月前
|
人工智能 Java 开发者
邀您参与 “直通乌镇” Spring AI Alibaba 开源竞技挑战赛!
邀您参与 “直通乌镇” Spring AI Alibaba 开源竞技挑战赛!
|
10月前
|
人工智能 数据可视化 Java
性能提升 10 倍, DIFY 模式迁移至 Spring AI Alibaba 模式 零改造实现
将 Dify 应用迁移至 Spring AI Alibaba,可兼顾可视化开发效率与代码工程灵活性,显著提升系统性能与扩展能力,适用于复杂 AI 业务场景。
1371 0