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