Nacos作为配置中心

Posted TimeSay

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nacos作为配置中心相关的知识,希望对你有一定的参考价值。

一、原理

 1、配置⼀致性模型

  Nacos 配置管理⼀致性协议分为两个大部分,第⼀部分是 Server 间⼀致性协议,⼀个是 SDK 与Server 的⼀致性协议,配置作为分布式系统中非强⼀致数据,在出现脑裂的时候可用性高于⼀致性,因此阿里配置中心是采用 AP ⼀致性协议。

 2、Server 间的⼀致性协议

有 DB 模式(读写分离架构)
  ⼀致性的核心是 Server 与 DB 保持数据⼀致性,从而保证 Server 数据⼀致;Server 之间都是对等的。数据写任何⼀个 Server,优先持久化,持久化成功后异步通知其他节点到数据库中拉取最新配置值,并且通知写入成功。

无 DB 模式 
  Server 间采用 Raft 协议保证数据⼀致性,行业大部分产品采用此模式,因此不展开介绍。Nacos提供此模式,是方便用户本机运行,降低对存储依赖。 
3、SDK 与 Server 的⼀致性协议 
  SDK 与 Server ⼀致性协议的核心是通过 MD5 值是否⼀致,如果不⼀致就拉取最新值。
Nacos 1.X 
  Nacos 1.X 采用 Http 1.1 短链接模拟长链接,每 30s 发⼀个心跳跟 Server 对比 SDK 配置 MD5 值是否跟 Server 保持⼀致,如果⼀致就 hold 住链接,如果有不⼀致配置,就把不⼀致的配置返回,然后 SDK 获取最新配置值。
Nacos 2.X
  Nacos 2.x 相比上面 30s ⼀次的长轮训,升级成长链接模式,配置变更,启动建立长链接,配置变更服务端推送变更配置列表,然后 SDK 拉取配置更新,因此通信效率大幅提升。

二、使用

 Nacos服务端初始化:

1、启动Nacos Server。

2、启动好Nacos之后,在Nacos添加如下的配置:

Data ID:   nacos-config.properties
Group  :    DEFAULT_GROUP
配置格式:  Properties
配置内容: user.name=nacos-config-properties
               user.age=90

注意dataId是以 properties(默认的文件扩展名方式)为扩展名。

客户端的使用方式:

如果要在项目中使用 Nacos 来实现应用的外部化配置,使用 group ID 为 com.alibaba.cloud 和 artifact ID 为 spring-cloud-starter-alibaba-nacos-config 的 starter。

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

现在就可以创建一个标准的 Spring Boot 应用。

@SpringBootApplication
public class ProviderApplication 

    public static void main(String[] args) 
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args);
        String userName = applicationContext.getEnvironment().getProperty("user.name");
        String userAge = applicationContext.getEnvironment().getProperty("user.age");
        System.err.println("user name :"+userName+"; age: "+userAge);
    

在运行此 Example 之前, 必须使用 bootstrap.properties 配置文件来配置Nacos Server 地址,例如:

bootstrap.properties

spring.application.name=nacos-config
spring.cloud.nacos.config.server-addr=127.0.0.1:8848

注意当使用域名的方式来访问 Nacos 时,spring.cloud.nacos.config.server-addr 配置的方式为 域名:port。 例如 Nacos 的域名为abc.com.nacos,监听的端口为 80,则 spring.cloud.nacos.config.server-addr=abc.com.nacos:80。 注意 80 端口不能省略。

启动这个 Example,可以看到如下输出结果:

2018-11-02 14:24:51.638  INFO 32700 --- [main] c.a.demo.provider.ProviderApplication    : Started ProviderApplication in 14.645 seconds (JVM running for 15.139)
user name :nacos-config-properties; age: 90
2018-11-02 14:24:51.688  INFO 32700 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@a8c5e74: startup date [Fri Nov 02 14:24:51 CST 2018]; root of context hierarchy
2018-11

基于 dataId 为 yaml 的文件扩展名配置方式

spring-cloud-starter-alibaba-nacos-config 对于 yaml 格式也是完美支持的。这个时候只需要完成以下两步:

1、在应用的 bootstrap.properties 配置文件中显示的声明 dataId 文件扩展名。如下所示

bootstrap.properties

spring.cloud.nacos.config.file-extension=yaml

2、在 Nacos 的控制台新增一个dataId为yaml为扩展名的配置,如下所示:

Data ID:        nacos-config.yaml

Group  :        DEFAULT_GROUP

配置格式:        YAML

配置内容:        user.name: nacos-config-yaml
                user.age: 68

这两步完成后,重启测试程序,可以看到如下输出结果。

2018-11-02 14:59:00.484  INFO 32928 --- [main] c.a.demo.provider.ProviderApplication:Started ProviderApplication in 14.183 seconds (JVM running for 14.671)
user name :nacos-config-yaml; age: 68
2018-11-02 14:59:00.529  INFO 32928 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@265a478e: startup date [Fri Nov 02 14:59:00 CST 2018]; root of context hierarchy

支持配置的动态更新

spring-cloud-starter-alibaba-nacos-config 也支持配置的动态更新,启动 Spring Boot 应用测试的代码如下:

@SpringBootApplication
public class ProviderApplication 

    public static void main(String[] args) 
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args);
        while(true) 
            //当动态配置刷新时,会更新到 Enviroment中,因此这里每隔一秒中从Enviroment中获取配置
            String userName = applicationContext.getEnvironment().getProperty("user.name");
            String userAge = applicationContext.getEnvironment().getProperty("user.age");
            System.err.println("user name :" + userName + "; age: " + userAge);
            TimeUnit.SECONDS.sleep(1);
        
    

如下所示,当变更user.name时,应用程序中能够获取到最新的值:

user name :nacos-config-yaml; age: 68
user name :nacos-config-yaml; age: 68
user name :nacos-config-yaml; age: 68
2018-11-02 15:04:25.069  INFO 32957 --- [-127.0.0.1:8848] o.s.boot.SpringApplication               : Started application in 0.144 seconds (JVM running for 71.752)
2018-11-02 15:04:25.070  INFO 32957 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@10c89124: startup date [Fri Nov 02 15:04:25 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@6520af7
2018-11-02 15:04:25.071  INFO 32957 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6520af7: startup date [Fri Nov 02 15:04:24 CST 2018]; root of context hierarchy
//从 Enviroment 中 读取到更改后的值
user name :nacos-config-yaml-update; age: 68
user name :nacos-config-yaml-update; age: 68

可以通过配置 spring.cloud.nacos.config.refresh.enabled=false 来关闭动态刷新

可支持profile粒度的配置

spring-cloud-starter-alibaba-nacos-config 在加载配置的时候,不仅仅加载了以 dataId 为 $spring.application.name.$file-extension:properties 为前缀的基础配置,还加载了dataId为 $spring.application.name-$profile.$file-extension:properties 的基础配置。在日常开发中如果遇到多套环境下的不同配置,可以通过Spring 提供的 $spring.profiles.active 这个配置项来配置。

spring.profiles.active=develop

$spring.profiles.active 当通过配置文件来指定时必须放在 bootstrap.properties 文件中。

Nacos 上新增一个dataId为:nacos-config-develop.yaml的基础配置,如下所示:

Data ID:        nacos-config-develop.yaml

Group  :        DEFAULT_GROUP

配置格式:        YAML

配置内容:        current.env: develop-env

启动 Spring Boot 应用测试的代码如下:

@SpringBootApplication
public class ProviderApplication 

    public static void main(String[] args) 
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args);
        while(true) 
            String userName = applicationContext.getEnvironment().getProperty("user.name");
            String userAge = applicationContext.getEnvironment().getProperty("user.age");
            //获取当前部署的环境
            String currentEnv = applicationContext.getEnvironment().getProperty("current.env");
            System.err.println("in "+currentEnv+" enviroment; "+"user name :" + userName + "; age: " + userAge);
            TimeUnit.SECONDS.sleep(1);
        
    

启动后,可见控制台的输出结果:

in develop-env enviroment; user name :nacos-config-yaml-update; age: 68
2018-11-02 15:34:25.013  INFO 33014 --- [ Thread-11] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6f1c29b7: startup date [Fri Nov 02 15:33:57 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@63355449

如果需要切换到生产环境,只需要更改 $spring.profiles.active 参数配置即可。如下所示:

spring.profiles.active=product

同时生产环境上 Nacos 需要添加对应 dataId 的基础配置。例如,在生成环境下的 Nacos 添加了dataId为:nacos-config-product.yaml的配置:

Data ID:        nacos-config-product.yaml

Group  :        DEFAULT_GROUP

配置格式:        YAML

配置内容:        current.env: product-env

启动测试程序,输出结果如下:

in product-env enviroment; user name :nacos-config-yaml-update; age: 68
2018-11-02 15:42:14.628  INFO 33024 --- [Thread-11] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6aa8e115: startup date [Fri Nov 02 15:42:03 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@19bb07ed

此案例中通过 spring.profiles.active=<profilename> 的方式写死在配置文件中,而在真正的项目实施过程中这个变量的值是需要不同环境而有不同的值。这个时候通常的做法是通过 -Dspring.profiles.active=<profile> 参数指定其配置来达到环境间灵活的切换。

支持自定义 namespace 的配置

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

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

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

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

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

支持自定义 Group 的配置

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

spring.cloud.nacos.config.group=DEVELOP_GROUP

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

支持自定义扩展的 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。

配置的优先级

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

完全关闭配置

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

SpringCloud Alibaba 使用Nacos作为配置中心及配置隔离讲解

一、Nacos作为服务配置中心

在上篇文章中我们讲解了使用Nacos作为配置中心,本篇我们继续讲下Nacos的配置中心功能。

上篇文章地址:https://blog.csdn.net/qq_43692950/article/details/122101863

在前我们讲解Spring Cloud 全家桶的文章中我们讲解了Spring Cloud Config 作为配置中心,配置主要存放在了Git中,但应该可以发现一些不足之处,比如没有一个可视化的页面管理配置信息,还有在修改配置后需要通知服务去刷新配置,即使整合了Bus,也要调用Config Server端的接口。而新一代的Nacos 就已经完善了这些问题,可以让我们更加方便的管理配置。

有兴趣的小伙伴也可以看下Spring Cloud Config的使用过程,可以参考下面我的博客:

SpringCloud H版 Config 配制中心讲解:https://blog.csdn.net/qq_43692950/article/details/122024549

SpringCloud H版 Config+Bus 实现全局配制刷新:https://blog.csdn.net/qq_43692950/article/details/122025347

下面就让我们体验下Naocs配置中心的功能,在开始前请安装好Nacos。

二、使用Nacos作为配置中心

新建一个SpringBoot 的 Module ,在pom中引入以下依赖:

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

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
    <groupId>com.bxc</groupId>
    <artifactId>common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

其中common使我们在前几篇文章中写的公共的module,主要封装了controller 的返回,如果不添加,将controller的返回修改为自己的即可。

下面修改配置文件,注意不要写在application.yml 中,需要新建一个bootstrap.yml文件,写在bootstrap.yml中,用来在程序引导时执行。

server:
  port: 8080

spring:
  application:
    name: nacos-config-client
  profiles:
    active: dev # 表示开发环境
#    active: test # 表示测试环境
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.40.1:8848
      config:
        server-addr: 192.168.40.1:8848
        file-extension: yaml

management:
  endpoint:
    shutdown:
      enabled: false
  endpoints:
    web:
      exposure:
        include: "*"

主启动类:

@SpringBootApplication
@EnableDiscoveryClient
public class NacosConfigApplication 
    public static void main(String[] args) 
        SpringApplication.run(NacosConfigApplication.class, args);
    

启动服务:

我们的服务已经注册到nacos中了,下面开始在nacos中新建配置信息:

首先我们在默认的命名空间和默认的组下,新建个配置文件。


上面主要点我标记出来了,其中需要注意的是Data ID 的命名规范是
$spring.application.name-$spring.profiles.active.$spring.cloud.nacos.config.file-extension,所以根据我们上面我们的配置信息 Data ID 的命名就应该是 nacos-config-client-dev.yaml
配置内容我们可以填写:

param: 
  text: abc
  name: ggg

配置完成后点发布即可。

下面在我们项目中新建一个读取配置信息的类:

@Component
@ConfigurationProperties(prefix = "param")
@Data
@RefreshScope
public class ParamProperties 
    private String text;
    private String name;

注意添加上@RefreshScope注解,可以实现配置内容动态刷新,下面可以看到这个效果。

再新建一个测试入口:

@Slf4j
@RestController
@RequestMapping("config")
public class ConfigController 

    @Autowired
    ParamProperties paramProperties;

    @GetMapping("/getConfig")
    public ResponseTemplate getConfig() 
        log.info("text: ", paramProperties.getText());
        log.info("name: ", paramProperties.getName());
        return ResSuccessTemplate.builder().build();
    

重启项目,在浏览器中访问: http://localhost:8080/config/getConfig ,查看控制台打印的信息:

可见已经读取到了我们的配置信息,下面可以在nacos中修改下配置内容:

对内容加了个55,点击发布、确认发布,后再次请求接口:

可见我们在没有重启服务器的情况下,就已经刷新了配置内容,但是前提是添加了@RefreshScope注解。

三、命名空间和分组

上面已经实现了动态配置功能,但是仔细想想还是有些问题,比如我们服务的数量特别多,每个配置都存放在 public 命名空间下,配置那么多也有些不好管理。甚至有可能造成误修改的错误。因此nacos提供者了 命名空间Namespace 和分组 Group 以及Cluster 的隔离方式。

默认情况:

Namespace=public,Group=DEFAULT_GROUP, 默认Cluster是DEFAULT

  • Nacos默认的命名空间是public,Namespace主要用来实现隔离。
    比方说我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。

  • Group默认是DEFAULT_GROUP,Group可以把不同的微服务划分到同一个分组里面去

  • Service就是微服务;一个Service可以包含多个Cluster(集群),Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。
    比方说为了容灾,将Service微服务分别部署在了杭州机房和广州机房,
    这时就可以给杭州机房的Service微服务起一个集群名称(HZ),
    给广州机房的Service微服务起一个集群名称(GZ),还可以尽量让同一个机房的微服务互相调用,以提升性能。

  • 最后是Instance,就是微服务的实例。

下面我们实现对 Namespace 和 Group 进行配置的隔离:

首先在Nacos 中新建一个 Namespace :



将命名空间的ID配置到我们的项目中,修改配置文件:

spring:
  application:
    name: nacos-config-client
  profiles:
    active: dev # 表示开发环境
#    active: test # 表示测试环境
    #active: info
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.40.1:8848
      config:
        server-addr: 192.168.40.1:8848
        file-extension: yaml
        group: TEST_GROUP
        namespace: c6e530b7-5d09-4a51-ad44-9b0c9e39fc11

主要添加了 group 和 namespace 两个配置,其中 namespace 就是对应上面的 命名空间ID ,group 我们在新建配置时,指定为 TEST_GROUP。

下面在myconfig的命名空间下,新建配置:


其中这里的分组Group就填写上面,我们在项目中配置的 TEST_GROUP,下面点击发布,并重启我们的项目。

在浏览器中访问: http://localhost:8080/config/getConfig ,查看控制台打印的信息:

已经读取到我们这个命名空间 和 分组下的配置信息。


喜欢的小伙伴可以关注我的个人微信公众号,获取更多学习资料!

以上是关于Nacos作为配置中心的主要内容,如果未能解决你的问题,请参考以下文章

nacos 作为配置中心使用心得--配置使用

nacos简介以及作为注册/配置中心与Eurekaapollo的选型比较

Nacos作为注册中心,配置中心部署方案

spring boot使用nacos作为配置中心实践

Nacos配置中心用法详细介绍

Nacos配置中心用法详细介绍