业务中台如何正确开启Nacos配置中心?

介绍

    nacos是阿里18年开源的作为配置中心及服务发现的中间件,本文主要讨论其作为配置中心的一些功能及实现。 下图描述了spring cloud config Appollo Nacos三个配置中心的一些特性,个人比较倾向于nacos,因为nacos 部署、使用特别方便,跟spring整个生态无缝结合。

nacos架构图:

使用

    nacos由server client mysql组成,server包含配置管理及client获取配置的功能,数据由mysql存储,server通过http服务暴露配置,client使用http长轮询来获取server端配置的变更,通过监听器对变更数据进行处理,nacos也支持udp方式来推送配置的变更。来看下nacos的使用,现在主流应用都使用spring boot或者spring cloud, 所以看下spring boot及spring cloud结合nacos的使用。

spring boot使用方式:



1.引入依赖:
依赖的版本0.1.x对应spring boot 1.x,0.2.x对应spring boot 2.x,由于项目使用log4j2日志,所以需要去除logback依赖,并且log4j2日志的版本需要在2.7.0以上,推荐2.10.0版本

<dependency>  
    <groupId>com.alibaba.boot</groupId>
    <artifactId>nacos-config-spring-boot-starter</artifactId>
    <version>0.1.1</version>
    <exclusions>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </exclusion>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </exclusion>
    </exclusions>
</dependency>  


2.增加配置:
nacos.config.server-addr=127.0.0.1:8848
nacos.config.context-path=nacos

3.启动类增加annotation
@NacosPropertySource(dataId = "spring-boot-demo.properties", autoRefreshed = true)
@NacosPropertySource(dataId = "share.properties", groupId = Constants.DEFAULTGROUP, autoRefreshed = true, properties = @NacosProperties(namespace = "af0a428a-ff43-4971-8b3d-4eaf4ffcfbc9"))
可以配置多个注解获取多个属性源。注解中定义的信息是拉取配置需要用到的信息,dataId(必传)指属性源的id,一般是项目名称+profile+文件后缀,groupId指配置的分组,默认DEFAULT
GROUP,autoRefreshed 指定是否刷新,namespace 指定配置命名空间,比如不同区域服务可以使用不同命名空间。不同的分组和命名空间可以对配置进行不同维度的管理。

4.@Value(value = "${xx}") spring bean中使用该注解注入配置,不过使用这种方式无法实时刷新,因为sprint boot监听更新只是刷新了上下文environment对象中的配置,没有重新生成spring bean。

spring cloud使用方式:

1.引入依赖:
依赖的版本0.1.x对应spring boot 1.x,0.2.x对应spring boot 2.x,并且log4j2日志的版本需要在2.7.0以上,推荐2.10.0版本

<dependency>  
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>0.1.1.RELEASE</version>
</dependency>  


2.增加配置:
spring.cloud.nacos.config.context-path=nacos
spring.cloud.nacos.config.shared-dataids=common.properties
spring.cloud.nacos.config.refreshable-dataids=common.properties
spring.cloud.nacos.config.ext-config[0].dataId=ext.properties
spring.cloud.nacos.config.ext-config[0].refresh=true
spring.cloud.nacos.config.namespace=af0a428a-ff43-4971-8b3d-4eaf4ffcfbc9
spring.cloud.nacos.config.prefix=${spring.application.name}
spring.cloud.nacos.config.file-extension=properties
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
如上配置需要添加到bootstrap配置文件才可生效,可定义shared-dataids获取一些公共配置,使用ext-config获取额外配置,通过prefix和file-extension确定dataId,以上配置的namespace会作用于所有shared、 ext和应用的dataId,不像spring boot方式,不同的NacosPropertySource注解中的namespace会分别生效

3.spring bean增加@RefreshScope,通过@Value(value = "${xx}") 注入配置,该方式可以达到实时刷新效果,spring cloud通过监听变更会销毁bean,下次使用生成bean时重新注入属性达到刷新效果。

nacos实现

client拉取配置和感知配置变更的核心接口是ConfigService,定义了发布、删除、获取配置,添加删除监听器、获取server状态这些接口

String getConfig(String dataId, String group, long timeoutMs) throws NacosException;

void addListener(String dataId, String group, Listener listener) throws NacosException;

boolean publishConfig(String dataId, String group, String content) throws NacosException;

boolean removeConfig(String dataId, String group) throws NacosException;

void removeListener(String dataId, String group, Listener listener);

String getServerStatus();  

实现类NacosConfigService对配置的增删改查操作通过一个HttpAgent来访问server暴露的http服务来实现,NacosConfigService内部通过ClientWorker类来对不同http请求获取的配置进行check刷新

final ScheduledExecutorService executor;  
final ExecutorService executorService;  
/**
 * groupKey -> cacheData
 */
AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<Map<String, CacheData>>(  
    new HashMap<String, CacheData>());

ClientWorker内部的核心成员如上,cacheMap 维护了不同groupKey(通过dataId,group,namespace组成)到CacheData(配置数据)映射,每次注册监听器之后把对应配置信息放入这个map,之后通过executorService每10ms提交一个LongPollingRunnable的线程

executor.scheduleWithFixedDelay(new Runnable() {  
    public void run() {
        try {
            checkConfigInfo();
        } catch (Throwable e) {
            LOGGER.error("[" + agent.getName() + "] [sub-check] rotate check error", e);
        }
    }
}, 1L, 10L, TimeUnit.MILLISECONDS);

checkConfigInfo方法如下

public void checkConfigInfo() {  
    // 分任务
    int listenerSize = cacheMap.get().size();
    // 向上取整为批数
    int longingTaskCount = (int)Math.ceil(listenerSize / ParamUtil.getPerTaskConfigSize());
    if (longingTaskCount > currentLongingTaskCount) {
        for (int i = (int)currentLongingTaskCount; i < longingTaskCount; i++) {
            // 要判断任务是否在执行 这块需要好好想想。 任务列表现在是无序的。变化过程可能有问题
            executorService.execute(new LongPollingRunnable(i));
        }
        currentLongingTaskCount = longingTaskCount;
    }
}

通过executorService提交一个长轮询检查线程,代码比较长就不贴了,流程就是对每个CacheData(配置数据),检查配置当前版本跟本地配置文件最后变更时间是否一致确定配置是否刷新,刷新则通知监听器做对应处理,然后使用http请求(默认超时30s)server端这个地址/v1/cs/config/listener(长轮询),server端这个地址会保持连接,如果配置没有变更,请求会在停留30s后返回,如果有配置更变,请求会马上返回,client接收到配置变更,会更新本地配置文件并且更新版本号。

server端通过LongPollingService来完成保持连接的能力,核心成员如下:

final ScheduledExecutorService scheduler;

/**
 * 长轮询订阅关系
 */
final Queue<ClientLongPolling> allSubs;  

ClientLongPolling是一个线程,通过scheduler默认30s定时处理请求,如果server端接收到配置变更请求,则通过发布LocalDataChangeEvent事件,LongPollingService继承监听器,触发监听执行DataChangeTask,内部通过allSubs维护的异步请求上下文AsyncContext直接返回response。

spring boot集成nacos通过NacosPropertySourcePostProcessor,该类实现BeanFactoryPostProcessor及EnvironmentAware,通过nacos client获取配置放入spring 上下文,通过是否刷新来决定是否注册监听。

spring cloud通过NacosPropertySourceLocator,在PropertySourceBootstrapConfiguration这个ApplicationContextInitializer里加载属性源,监听ApplicationReadyEvent事件后为属性源注册监听处理变更。

使用感受

server端本地可通过standalone模式启动,也可源码直接运行,方便调试,client使用也很方便,支持配置分组和命名空间的隔离,支持配置刷新回滚,配置灰发功能还有待开发,权限管理不足,总体使用还是非常简单方便,spring 生态集成度很高,比较推荐使用。

### 如何在Spring Boot项目中加载Nacos配置文件 #### 配置背景说明 自 `Spring Cloud 2020.0.x` 版本起,默认情况下不再支持自动加载 `bootstrap.properties` 文件[^1]。因此,如果需要通过 Nacos 配置中心动态管理配置,则需手动启用相关功能。 --- #### 解决方案一:修改启动类以重新激活 Bootstrap 功能 为了使 Spring 应用能够正常加载 Nacos 的远程配置,可以在项目的主启动类中设置如下环境变量: ```java public class Application { public static void main(String[] args) { System.setProperty("spring.cloud.bootstrap.enabled", "true"); SpringApplication.run(Application.class, args); } } ``` 上述代码的作用是显式开启 `bootstrap` 阶段的功能,从而允许 Spring 在应用初始化阶段优先加载外部化配置[^3]。 --- #### 解决方案二:调整配置文件结构并引入必要依赖 确保项目中的 `pom.xml` 或 `build.gradle` 已经正确引入了 Nacos 和 Spring Cloud 的相关依赖项。以下是 Maven 示例: ```xml <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> ``` 随后,在本地创建一个名为 `application.properties` 或 `application.yml` 的基础配置文件,并添加以下内容来指定 Nacos 远程服务器地址及相关参数: ```yaml spring: application: name: demo-service cloud: nacos: config: server-addr: localhost:8848 # 替换为实际的Nacos服务地址 file-extension: yaml # 如果使用YAML格式则填写此字段 ``` 注意:由于默认行为的变化,建议将原本放置于 `bootstrap.properties` 中的内容迁移至此处。 --- #### 解决方案三:验证Nacos客户端连接状态 确认当前开发机器已成功安装并运行 Nacos Server 后,可通过命令行测试其可用性。例如进入 Nacos 安装路径下的 bin 目录执行脚本启动服务[^5]: ```bash sh startup.sh -m standalone ``` 接着访问浏览器页面 http://localhost:8848/nacos/index.html 登陆控制台界面查看是否存在目标数据集以及对应的 Group ID 和 Data ID 是否匹配应用程序所声明的信息。 --- #### 加载流程解析 当 Spring Boot 应用程序启动时,会触发一系列事件链路完成上下文构建工作流。其中涉及到的关键组件之一便是 `NacosPropertySourceLocator` ,它负责定位来自远端存储的服务实例元信息资源位置[^2] 。具体实现原理可参阅源码片段: ```java @Autowired(required = false) private List<PropertySourceLocator> propertySourceLocators; ``` 一旦此类对象被注入容器之后便会参与到全局属性集合组装过程中去,最终形成完整的配置视图供业务逻辑调用消费。 --- #### 命令行方式覆盖部分选项 除了以上提到的技术手段之外,还可以利用 JVM 参数或者 CLI 形式的开关快速定制某些特殊场景需求下的表现形式。比如强制绑定监听端口号或是额外追加其他静态资源配置文档的位置指示器等等[^4]: ```shell java -Dserver.port=9090 \ -jar target/demo-application.jar \ --spring.config.location=./custom-config/ ``` 这样做的好处是可以灵活应对不同部署环境下可能存在的差异情况而不必频繁改动原始工程定义本身。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天秤座的架构师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值