欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Nacos做配置中心

程序员文章站 2022-07-15 08:59:07
...

 从单体架构到微服务

单体架构
Web应用程序发展的早期,大部分web工程师将所有的功能模块打包到一起并放在一个web容器中运行,所有功能
模块使用同一个数据库,同时,它还提供API或者UI访问的web模块等。

 Nacos做配置中心

尽管也是模块化逻辑,但是最终它还是会打包并部署为单体式应用,这种将所有功能都部署在一个web容器中运行
的系统就叫做单体架构(也叫:巨石型应用)。
单体架构有很多好处:

  • 开发效率高:模块之间交互采用本地方法调用,并节省微服务之间的交互讨论时间与开发成本。
  • 容易测试:IDE都是为开发单个应用设计的、容易测试——在本地就可以启动完整的系统。
  • 容易部署:运维成本小,直接打包为一个完整的包,拷贝到web容器的某个目录下即可运行。

但是,上述的好处是有条件的,它适用于小型简单应用,对于大规模的复杂应用,就会展现出来以下的不足:

  • 复杂性逐渐变高,可维护性逐渐变差 :所有业务模块部署在一起,复杂度越来越高,修改时牵一发动全身。
  • 版本迭代速度逐渐变慢:修改一个地方就要将整个应用全部编译、部署、启动时间过长、回归测试周期过长。
  • 阻碍技术创新:若更新技术框架,除非你愿意将系统全部重写,无法实现部分技术更新。
  • 无法按需伸缩:通过冗余部署完整应用的方式来实现水平扩展,无法针对某业务按需伸缩。

微服务
许多大型公司,通过采用微服务架构解决了上述问题。其思路不是开发一个巨大的单体式的应用,而是将应用分解为小的、互相连接的微服务。
一个微服务一般完成某个特定的功能,比如订单服务、用户服务等等。每一个微服务都是完整应用,都有自己的业务逻辑和数据库。一些微服务还会发布API给其它微服务和应用客户端使用。
比如,根据前面描述系统可能的分解如下:

 Nacos做配置中心

每一个业务模块都使用独立的服务完成,这种微服务架构模式也影响了应用和数据库之间的关系,不像传统多个业务模块共享一个数据库,微服务架构每个服务都有自己的数据库。
微服务架构的好处:

  • 分而治之,职责单一;易于开发、理解和维护、方便团队的拆分和管理
  • 可伸缩;能够单独的对指定的服务进行伸缩
  • 局部容易修改,容易替换,容易部署,有利于持续集成和快速迭代
  • 不会受限于任何技术栈

 分布式应用配置管理
下图展示了如何通过Nacos集中管理多个服务的配置:

 Nacos做配置中心

用户通过 Nacos Server的控制台集中对多个服务的配置进行管理。各服务统一从 Nacos Server中获取各自的配置,并监听配置的变化。

发布配置
首先在nacos发布配置,我们规划了两个服务service1、service2,并且想对这两个服务的配置进行集中维护。打开nacos控制台,并点击菜单配置管理->配置列表:
在Nacos添加如下的配置:

 Nacos做配置中心

Nacos做配置中心

创建项目

  <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.3.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</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-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement> 

启动类:

@SpringBootApplication
@RestController
public class Service1Application {

    public static void main(String[] args) {
        SpringApplication.run(Service1Application.class, args);
    }

    @Autowired
    ConfigurableApplicationContext applicationContext;

    @GetMapping("/port")
    public String getPort() {
        //读取配置信息
       return applicationContext.getEnvironment().getProperty("server.port");
    }

    @GetMapping("/configs")
    public String getConfigs() {
        //读取配置信息
        return applicationContext.getEnvironment().getProperty("common.name");
    }

    @GetMapping(value = "/configs2")
    public String getConfigs2() {
        String name = applicationContext.getEnvironment().getProperty("common.name");
        String age = applicationContext.getEnvironment().getProperty("common.age");
        String address = applicationContext.getEnvironment().getProperty("common.address");
        String birthday = applicationContext.getEnvironment().getProperty("common.birthday");
        String fullname = applicationContext.getEnvironment().getProperty("common.fullname");
        return name + "+" + age + "+" + address + "+" + birthday + "+" + fullname;
    }

}  

配置

spring:
  application:
    name: service1
  cloud:
    nacos:
      config:
        server-addr: 47.156.271.569:8848  # 配置中心地址
        file-extension: yaml #dataid 的名称就是application的name加file-extension   service1.yaml
        namespace: e4582490-173d-41df-9932-c65f01605814 # 开发环境  指定 具体的namespace
        group: TEST_GROUP # 测试组  

开始测试,直接在线修改,支持动态刷新

 Nacos做配置中心

Nacos做配置中心

 Nacos做配置中心

 支持扩展dataid

配置如下:

spring:
  application:
    name: service1
  cloud:
    nacos:
      config:
        server-addr: 47.111.251.239:8848  # 配置中心地址
        file-extension: yaml #dataid 的名称就是application的name加file-extension   service1.yaml
        namespace: e4582490-173d-41df-9932-c65f01605814 # 开发环境  指定 具体的namespace
        group: TEST_GROUP # 测试组
        ext-config:
          - data-id: service2.yaml
            group: TEST_GROUP
            refresh: true
#        ext-config[0]:
#          data-id: service2.yaml
#          group: TEST_GROUP
#          refresh: true  

上图中的2种配置都可以,上面是即定义了group和支持刷新。 

可以看到 :

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

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

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

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

Nacos做配置中心

 注意:共享dataid的时候默认DEFAULT_GROUP,不是这个组的话,是读取不到的

spring:
  application:
    name: service1
  cloud:
    nacos:
      config:
        server-addr: 47.151.545.265:8848  # 配置中心地址
        file-extension: yaml #dataid 的名称就是application的name加file-extension   service1.yaml
        namespace: e4582490-173d-41df-9932-c65f01605814 # 开发环境  指定 具体的namespace
        group: TEST_GROUP # 测试组
        shared-dataids: ext-config-common01.properties,ext-config-common02.properties,ext-config-common03.properties
        refreshable-dataids: ext-config-common01.properties

Nacos做配置中心

可以看到:

  • 通过 spring.cloud.nacos.config.shared -dataids 来支持多个共享 Data Id 的配置,多个之间用逗号隔开。
  • 通过 spring.cloud.nacos.config.refreshable -dataids 来支持哪些共享配置的 Data Id 在配置变化时,应用中是否可动态刷新, 感知到最新的配置值,多个 Data Id 之间用逗号隔开。如果没有明确配置,默认情况下所有共享配置的 Data Id 都不支持动态刷新。

Note:通过 spring.cloud.nacos.config.shared -dataids 来支持多个共享配置的 Data Id 时, 多个共享配置间的一个优先级的关系我们约定:按照配置出现的先后顺序,即后面的优先级要高于前面。
Note:通过 spring.cloud.nacos.config.shared -dataids 来配置时,Data Id 必须带文件扩展名,文件扩展名既可支持 properties,也可以支持 yaml/yml。 此时 spring.cloud.nacos.config.file -extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响。
Note: spring.cloud.nacos.config.refreshable -dataids 给出哪些需要支持动态刷新时,Data Id 的值也必须明确给出文件扩展名。

配置的优先级
Spring Cloud Alibaba Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置。
A: 通过 spring.cloud.nacos.config.shared -dataids 支持多个共享 Data Id 的配置
B: 通过 spring.cloud.nacos.config.ext -config[n].data-id 的方式支持多个扩展 Data Id 的配置,多个Data Id 同时配置时,他的优先级关系是 spring.cloud.nacos.config.ext -config[n].data-id 其中 n 的值越大,优先级越高。
C: 通过内部相关规则(应用名、扩展名 )自动生成相关的 Data Id 配置
当三种方式共同使用时,他们的一个优先级关系是:C > B >A

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