Nacos做配置中心

 从单体架构到微服务

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

 

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

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

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

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

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

 

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

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

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

 

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

发布配置
首先在nacos发布配置,我们规划了两个服务service1、service2,并且想对这两个服务的配置进行集中维护。打开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 # 测试组  

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

 

 

 支持扩展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 ,你可以通过以下的方式来配置:

 注意:共享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

可以看到:

  • 通过 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

posted @ 2020-04-25 11:35  天宇轩-王  阅读(1336)  评论(0编辑  收藏  举报