多环境配置
[一]什么是多环境配置?
在实际项目开发过程中,我们往往需要区分开发,测试,联调,预发布,生产等不同的应用环境。这些应用环境用途不同,对应环境的配置项、稳定性、数据质量、保障性、可接触人群等要求也不同,比如 Swagger 一般上在生产时是关闭的;不同环境数据库地址,端口号等都是不尽相同的。要是没有多环境的自由切换,部署起来是很繁琐也容易出错的。
使用多环境配置,可以针对不同的应用环境,提前配置好对应的环境配置信息。在使用时,仅需要修改具体的环境名称,就可以把对应环境配置信息,系统参数等相关内容全部切换。不仅使用便捷,还极大地降低了手工修改参数的出错率。
[二]不同套件中多环境
[1]Maven 多环境配置
使用Maven
可以通过在pom.xml
中增加<profiles>
配置进行多环境的配置。参见以下示例:
<profiles>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
...
</properties>
</profile>
<profile>
<id>produtction</id>
<properties>
...
</properties>
</profile>
<profile>
<id>testing</id>
<properties>
...
</properties>
</profile>
</profiles>
通过下面配置就可以指定当前默认的环境是哪个
<activation>
<activeByDefault>true</activeByDefault>
</activation>
在开发和使用过程中,必须要配置一个默认的环境。配置完成之后,在 IDE 中也会提供可操作性界面进行操作。下图即为 IDEA 的界面示例:
[1]Spring Boot 多环境配置
Spring Boot 环境设置机制
spring.profiles.active
属性可以为我们指定当前设置的环境,以此来选择我们的配置文件。例如我们有配置文件
- application.yml
- application-dev.yml
- application-test.yml
- application-prod.yml
当执行 java -jar xxx.jar --spring.profiles.actvie=test
此时,系统将启用 application.yml
和 application-test.yml
配置文件。
当执行 java -jar xxx.jar --spring.profiles.actvie=prod
此时,系统将启用 application.yml
和 application-prod.yml
配置文件。
正是这种配置参数可以决定我们使用哪种配置文件,如果我们把不同环境的配置写在对应的配置文件中,我们就可以实现多环境机制。
配置多环境
正如上一点所述,我们配置不同的配置文件
- application.yml
- application-dev.yml(开发环境)
- application-test.yml(测试环境)
- application-uat.yml(预发布环境)
- application-prod.yml(生产环境)
指定环境
- 在 cmd 命令中指定
java -jar xxx.jar --spring.profiles.actvie=dev
- 在
application.yml
中指定
spring:
profiles:
active: dev
- 在 IDEA 编辑器中指定
在运行按钮(绿色三角形按钮)旁边选择 Edit Configurations...
,在弹出的对话框中 Active profiles
输入 dev
或其他即可。
注意
这种方法只有在本地调试的时候才生效。
单一文件写法
spring:
application:
name: @artifactId@
profiles:
active: develpment
...
---
# 开发环境配置
spring:
config:
activate:
on-profile: develpment
---
# 生产环境配置
spring:
config:
activate:
on-profile: production
[3]Nacos 多环境配置
本身没有提供统一的多环境管理。在 Nacos 中,本身有多个不同管理级别的概念,包括:Data ID、Group、Namespace。只要利用好这些层级概念的关系,就可以根据自己的需要来实现多环境的管理。
Data Id
Data Id
的默认值为${spring.cloud.nacos.config.prefix}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
spring.cloud.nacos.config.prefix
的默认值为${spring.application.name}
spring.cloud.nacos.config.file-extension
的默认值为properties
- 当
spring.profiles.active
未配置时,则匹配${spring.application.name}.properties
- 若设置了
spring.profiles.active
而Nacos
中存在${spring.application.name}.properties
时,若还存在 ${spring.application.name}-${spring.profiles.active}.properties
,则默认匹配后者,若不存在,则会自动匹配前者 由于Nacos
建议且默认用spring.application.name
作为Data Id
的前缀,若要在不同服务中共享项目统一配置,则可以通过配置spring.cloud.nacos.config.shared-dataids
或spring.cloud.nacos.config.refreshable-dataids
来添加共享配置,前者不支持自动刷新,后者支持
Group
Group
是一个很灵活的配置项,并没有固定的规定,可以用作多环境,多模块,多版本之间区分配置
Namespace
使用命名空间来区分不同环境的配置,因为使用profiles
或group
会是不同环境的配置展示到一个页面,而Nacos
控制台对不同的Namespace
做了Tab
栏分组展示
创建方式如下图所示
警告
配置 Namespace 的时候不是通过名称,而是通过命名空间的 ID(上图所示),可通过如下配置来设置服务使用的命名空间
[4]Docker 和 K8S 多环境配置
Docker
和K8S
的多环境,因为不同使用者使用的方式不同,Dante Cloud 并没有过多涉及。Dante Cloud 中,也简单定义了自己Docker
多环境,涉及production
和development
两个环境,主要区别是production
环境 docker 打包会包含Skywalking Agent
,而development
环境 docker 打包只会包含应用,通过执行不同的docker-compose
文件进行区分仅此而已。如果不使用Skywalking
,使用development
环境打包 docker 即可。
[三]Dante Cloud 的多环境配置
微服务架构涉及多方面内容,Dante Cloud的为解决多环境,综合使用Maven
,Spring Boot
以及Nacos
多环境的特点,以支持微服务的多环境切换和多种数据库的配置支持。
[1]Maven 与 Spring Boot 多环境联动
Dante Cloud Maven 多环境配置,在工程根目录下的pom.xml
中进行配置。如下所示:
<profile>
<id>development</id>
<activation>
<!--默认激活配置-->
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<!--当前环境-->
<profile>development</profile>
<database>postgresql</database>
<!--基础设施:tencent、alibaba、original-->
<facility>alibaba</facility>
<!--代码构建控制-->
<!--跳过构建源代码包-->
<skip.build.source.package>false</skip.build.source.package>
<!--不copy代码包到docker构建目录-->
<skip.copy.docker.resource>true</skip.copy.docker.resource>
<!--不执行git commit 构建-->
<skip.build.git.commit.info>false</skip.build.git.commit.info>
<!--Spring Cloud Alibaba 配置中心命名空间,用于支持多环境.这里必须使用ID,不能使用名称,默认为空-->
<alibaba.namespace>00a14001-348d-40a7-82aa-e2e032f6e03c</alibaba.namespace>
<!--Spring Cloud Alibaba 配置中心地址-->
<alibaba.config.server-addr>192.168.101.10:8848</alibaba.config.server-addr>
<!--Spring Cloud Alibaba 服务发现地址-->
<alibaba.discovery.server-addr>192.168.101.10:8848</alibaba.discovery.server-addr>
<tencent.polaris.namespace>herodotus-reactive</tencent.polaris.namespace>
<!--Spring Cloud Tencent 配置 【(8091)grpc/tcp,默认注册中心端口;(8090)http/tcp,默认注册中心端口】-->
<tencent.polaris.server-addr>192.168.101.10:8091</tencent.polaris.server-addr>
<!--Spring Cloud Tencent Config 配置 【(8093)grpc/tcp,默认配置中心端口】-->
<tencent.polaris.config-addr>192.168.101.10:8093</tencent.polaris.config-addr>
<!--Spring Cloud Tencent 本地缓存目录-->
<tencent.polaris.local.dir>./configurations/backup/cache</tencent.polaris.local.dir>
<!--Spring Cloud Tencent 动态配置数据源类型 polaris: 从北极星服务端获取配置文件 local: 从本地磁盘读取配置文件-->
<tencent.polaris.data.source>polaris</tencent.polaris.data.source>
</properties>
</profile>
所谓实现 Maven 与 Spring Boot 多环境联动
,即 pom.xml
中定义的值可以传递到 Spring Boot 的配置文件。这里是利用 @
标记进行实现。
在 Spring Boot 的配置中,通过配置 @@
,就可以获取到 pom.xml
中 <profile>
中定义的变量。通过这种方式,既实现了 Maven 参数向 Spring Boot 配置的传递,又实现了 Maven 对 Spring Boot 多环境的联动。
server:
port: 8846
spring:
application:
name: @artifactId@ #拿到POM文件中的值
profiles:
active: @facility@
---
# spring cloud alibaba 基础设施配置
spring:
config:
activate:
on-profile: alibaba
cloud:
nacos:
config:
namespace: ${ALIBABA_NAMESPACE:@alibaba.namespace@}
server-addr: ${ALIBABA_CONFIG_SERVER_ADDR:@alibaba.config.server-addr@}
file-extension: yaml
shared-configs:
- data-id: herodotus-cloud-environment.yaml
group: ${PROFILE:@profile@}
- data-id: herodotus-cloud-platform.yaml
group: common
- data-id: herodotus-cloud-database-${DATABASE:@database@}.yaml
group: common
- data-id: herodotus-cloud-database.yaml
group: common
- data-id: herodotus-cloud-redis.yaml
group: common
- data-id: herodotus-cloud-cache.yaml
group: common
- data-id: herodotus-cloud-rest.yaml
group: common
- data-id: herodotus-cloud-kafka.yaml
group: common
# 本地存储模式必须要包含
# 远程存储:social 配置在 upms
# 本地存储:social 配置在 uaa
- data-id: herodotus-cloud-social.yaml
group: common
- data-id: ${spring.application.name}.yaml
group: service
discovery:
namespace: ${ALIBABA_NAMESPACE:@alibaba.namespace@}
server-addr: ${ALIBABA_DISCOVERY_SERVER_ADDR:@alibaba.discovery.server-addr@}
sentinel:
transport:
port: 8719
dashboard: ${ALIBABA_SENTINEL_SERVER_ADDR:@alibaba.sentinel.server-addr@}
eager: true #服务注启动,直接注册到dashboard
---
# spring cloud tencent 基础设施配置
spring:
config:
activate:
on-profile: tencent
注意
通过 @@
调用 pom.xml
中变量的方式,因为其本质是利用 maven 的插件,在代码编译过程中进行的静态替换。正因为如此, pom.xml
中的变量一旦进行了修改,就必须重新编译代码
[2]Spring Boot 与 Nacos 多环境联动
Nacos 本身并不支持多环境,但是可以利用 Nacos 配置机制来实现。Nacos 配置核心概念有 Data ID、Group、Namespace。Namespace 本身不适合用来实现多环境,因为通常一个系统只会对应一个 Namespace。Group 就非常适合来做多环境。
Dante Cloud 通过在 Nacos 中定义不同的 Group,根据不同的 Profile 调用不同 Group 中的配置,来实现 Spring Boot 与 Nacos 多环境联动。通过下面的代码,可以看到 group: ${PROFILE:@profile@}
配置。利用这个配置就实现了 Spring Boot 多环境与 Nacos Group 的联动。
server:
port: 8846
spring:
application:
name: @artifactId@ #拿到POM文件中的值
profiles:
active: @facility@
---
# spring cloud alibaba 基础设施配置
spring:
config:
activate:
on-profile: alibaba
cloud:
nacos:
config:
namespace: ${ALIBABA_NAMESPACE:@alibaba.namespace@}
server-addr: ${ALIBABA_CONFIG_SERVER_ADDR:@alibaba.config.server-addr@}
file-extension: yaml
shared-configs:
- data-id: herodotus-cloud-environment.yaml
group: ${PROFILE:@profile@}
.....
---
# spring cloud tencent 基础设施配置
spring:
config:
activate:
on-profile: tencent
[3]总结
通过以上内容的讲解,我们可以了解到 Dante Cloud 的多环境配置设计并不复杂。核心就是:
利用 Spring Boot 自身的多环境机制和 Nacos 的 Group 机制,通过 @@
标记获取到 pom.xml
中定义的变量,最终实现 Maven、Spring Boot 和 Nacos 的联动以及多环境的统一配置
提示
因此,在部署本系统、修改配置的步骤中,一定要明确自己所选的多环境
。 如果 pom.xml
中,当前激活的是 development
<profile>
,那么对应的就应该修改 Nacos 中,development
Group 下对应的配置。