spring cloud下用nacos作配置中心的初步探究,替换spring config server

一, 背景:

1, 引入nacos来作配置中心java

项目如今用的是spring cloud netflix,没有用到spring-cloud-alibaba的全家桶,但又想用到nacos来作配置中心,故按官网提供的方式是不行的git

 

2, 探究下nacos配置中心的使用与实现github

目前用的spring config server其实弊端不少,好比: 强依赖gitLab, 加入BUS复杂度高很差确保全部节点的更新等缺点spring

故,想用nacos去替换下当前的配置中心数据库

 

 

二, 引入

 

1, 如何在spring cloud netflix中引入nacos相关?

官网是假设已经引入了spring-cloud-alibaba的,故直接引入bootstrap

其实都是基于spring-cloud的标准,故直接引入spring cloud alibaba nacos相关适配JAR包便可,但也都有引入spring-cloud-commons,须要主要版本的适配markdown

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-config -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>0.1.1.RELEASE</version>
        </dependency>

而后在bootstrap.yml中加入相关配置,如app

spring:
 cloud:
  nacos:
   config:
    server-addr: 10.1.5.101:8848

而后和官网同样了, 默认的dataId是this

${spring.application.name}-${spring.profile.active}.${file-extension}spa

其中 file-extension 默认为 properties

 

如,项目名为 test

那么active为local的默认dataId为

test-local.properties

 

三, nacos的使用

哪些配置能够热更新

 

这里其实和config server的用法同样,也是实现了spring cloud config的标准

1), spring boot 的 自动装配模式的能够直接热更新

如:

@ConfigurationProperties(PREFIX)
public class TestSentinelConfig {
	public static final String PREFIX = "test.sentinel";
	private String values;
	

	public String getValues() {
		return values;
	}

	public void setValues(String values) {
		this.values = values;
	}
}

 

2) , 加了做用域@RefreshScope的,如: @Value("${value}")模式注入的话,须要在bean上加入RefreshScope标签

@RefreshScope
@RestController
public class TestOnly {
@Value("${testConfig.value1}")
private String value;
 
@RequestMapping("test/test")
public String test() {
return value;
}
}

 

四,实现原理探究

nacos是经过长轮询,拉取最新配置的,拉去到最新配置后,在spring 的context里进行事件发布一个RefreshEvent。

 轮询发布事件具体源码:

入口, nacos client 中

ClientWorker -> 

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

更多nacos client的细节

 

10L一次 执行一次checkConfigInfo() 

而后nacos的spring cloud的适配器,spring-cloud-starter-alibaba-nacos-config进行适配

遇到更新便发布RefreshEvent  #org.springframework.cloud.alibaba.nacos.refresh.NacosContextRefresher$1.receiveConfigInfo

...
                    refreshHistory.add(dataId, md5);
                    applicationContext.publishEvent(
                            new RefreshEvent(this, null, "Refresh Nacos config"));

....

这部分 更多spring cloud alibaba nacos源码细节实现 

 再日后,就是spring cloud context自己的实现了,这部分和spring config server是同样的了

而后后续就和spring config server的同样了

org.springframework.cloud.endpoint.event.RefreshEventListener 监听  -->

核心部分 ContextRefresher#refresh()

public synchronized Set<String> refresh() {
        Map<String, Object> before = extract(
                this.context.getEnvironment().getPropertySources());
        addConfigFilesToEnvironment();
        Set<String> keys = changes(before,
                extract(this.context.getEnvironment().getPropertySources())).keySet();
        this.context.publishEvent(new EnvironmentChangeEvent(keys));
        this.scope.refreshAll();
        return keys;
    }

这部分网上分析的资料就比较多了,和原来咱们用spring config server 访问refresh实际上是一个意识了

更多spring cloud common这部分的细节

 

这部分简单说就是nacos client长轮询dataId的修改,而后通知到spring cloud alibaba的适配器,经过spring cloud common部分进行热更新属性。

 

五,遗留问题

1, 这部分集群的策略还得探究

2, 对于配置信息的数据库的持久化还没加上

3,如何替代spring config server的版本控制策略,用group么

4,是否要用到nacos的注册中心去替代eureka,待研究

 

公众号:

相关文章
相关标签/搜索