SpringCloud中使用Nacos作为配置中心原理

使用了是Nacos的自动配置依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2.2.5.RELEASE</version>
</dependency>

bootstrap.yml配置文件

spring:
  cloud:
    nacos:
      # Nacos 控制台添加配置:
      # Data ID:example.properties
      # Group:DEFAULT_GROUP
      config:
        server-addr: 127.0.0.1:8848
        prefix: example
        # 指定配置的后缀,支持 properties、yaml、yml,默认为 properties
        file-extension: properties
        username: nacos
        password: nacos

使用到nacos配置中心的bean上配置@RefreshScope 注解,标识这个bean的作用域

@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
    @Value("${useLocalCache:false}")
    private boolean useLocalCache;
    
    @RequestMapping("/get")
    public boolean get() {
        return useLocalCache;
    }
}

以上面的配置为例子。

先说下具体配置点

1、加载的nacos属性源列表有哪些?

默认会加载 group=DEFAULT_GROUP的属性源列表有:

1、带profile的 dataId配置源 dataId = ${prefix}-${spring.profiles.active}.${file-extension}

2、不带profile的 dataId配置源 dataId = ${prefix}.${file-extension}

3、不带后缀的 dataId配置源 dataId = ${prefix}

默认情况下 前缀 prefix = spring.application.name

加载属性源列表优先级为:

带profile的 DataId名称 > 带 .后缀的 dataId名称 > 不带 .后缀的 dataId名称

如上面的配置按照优先级,从高到底会加载

dataId = example-dev.properties
dataId = example.properties
dataId = example

2、nacos属性源是否覆盖本地配置文件和系统属性的设置

SpringCloud中,nacos是借助SpringCloud的Config来加载属性源的,所以是否覆盖系统属性和配置文件属性的设置也是通过SpringCloud的配置进行触发。

默认情况下的配置:

spring:
  cloud:
    config:
      # 是否不覆盖其他属性源,默认为false,即覆盖其他源
      override-none: false
      # 允许nacos被本地文件覆盖,默认为true
      allow-override: true
      # 是否覆盖系统属性源,默认为true
      override-system-properties: true

 默认情况下nacos属性源优先级最高,会覆盖系统属性源和配置属性源。

 
如果用户想复写上述的属性,则放在bootstrap.yml或application.yml配置文件中是无效的

如果要修改nacos的属性源优先级,则需要将 上述配置放到nacos上的配置内容中才生效!

当nacos属性源中有上面的配置参数时
会先判断
1、(!allow-override || (!override-none && override-system-properties))
    上面条件为真时,
    override-none: false
    allow-override: true
    override-system-properties: true
    会将nacos属性源添加到 environment的属性源列表第一位,
    即覆盖系统属性源,并且可以覆盖其他属性源
    propertySources.addFirst()

2、(override-none)
    不满足条件1,且条件2为真时。
    override-none: true
    allow-override: true
    override-system-properties: true
    即不覆盖其他属性源,将nacos属性源放到属性源列表最后面。
    propertySources.addLast()

3override-system-properties = false时,
    不满足条件1和2,上面条件通过
    会将nacos属性源添加到 系统属性源(systemEnvironment)后面,在其他配置文件之前。
    

所以当要让nacos优先级最高,使用默认spring.cloud.config配置即可。
当要让nacos属性源不覆盖本地配置文件,需要设置 override-none: true
当要让nacos属性源覆盖本地配置文件,但不覆盖系统属性源,设置 override-system-properties: false

启动过程:

1、SpringBoot的prepareEnvironment()方法初始化完系统环境属性源后,

  发布环境准备完成事件中,进行SpringCloud容器启动,会在这里进行Nacos的配置源加载到Environment中。

2、Nacos动态刷新配置属性相关bean定义的设置(@RefreshScope注解配置)

  @RefreshScope 注解标识 bean的生命周期(作用域)

@RefreshScope标识的bean:标识bean的生命周期为当前配置没发生变化的时间段内。

    即:当配置文件发生变化(配置content的MD5值发生变化时),

    会触发作用域:refresh的刷新操作。将会重新创建bean实例,放入到作用域bean实例列表中。

  具体查看资料:Spring系列四:Bean Scopes作用域:https://my.oschina.net/merryyou/blog/3119993

  如request作用域,标识为@RequestScope注解的bean,即等同于@Scope(WebApplicationContext.SCOPE_REQUEST),

    该bean的声明周期为一次http请求开始到结束。即每一次获取http请求获取到的bean对象实例都是新创建的。

    而在一个http请求内引用的bean对象实例都是相同的对象。

启动过程中作用域

如上面实例:ConfigController

有@RefreshScope注解,会被归类到作用域refresh下面,bean的创建,销毁都是由作用域来管理。

通过BeanFactory.getBean(String name) 方法获取 ConfigController实例时,

  会判断该bean是否属于Singleton单例, Prototype原型 类型

  如果都不是,则会用Scope作用域来获取bean实例。

  Scope.get(String name, ObjectFactory<?> objectFactory)方法

refresh作用域对应的Scope实现类: RefreshScope

SpringBoot运行过程中配置的刷新:

在自动配置类com.alibaba.cloud.nacos.NacosConfigAutoConfiguration
申明的配置刷新类:NacosContextRefresher
刷新事件处理类:RefreshEventListener 和 ContextRefresher

 当有配置变更时发布RefreshEvent事件,这个事件是RefreshEventListener监听

NacosConfigService内部维持了一个executor轮询线程(单线程,每隔0.01秒执行一次)和一个executorService处理数据线程。
轮询线程会检查配置数据的md5是否变化,发生变化再通知listener进行配置变更接收。

NacosContextRefresher向Nacos注册的监听器,会发布RefreshEvent事件
后面就通过Spring Cloud的刷新机制,进行环境配置属性的重新加载。对 scope作用域中 key为 "refresh" 下的bean进行重新生成。

作者:海绵般汲取
出处:https://www.cnblogs.com/gne-hwz/
版权:本文版权归作者和博客园共有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
原文地址:https://www.cnblogs.com/gne-hwz/p/15420271.html