在我们Java项目开发过程中,对于配置文件的多环境配置一般会采用以下方案:
那么本文将讲述第二个方案中一个能为任何项目提供统一配置的管理方式:Spring Cloud Config。
客户端和服务端上映射的概念与Spring Environment和PropertySource抽象相同,因此适用于任何Spring应用程序。
由于配置文件通常是可读文本格式,所以Spring Cloud Config理论能为任何应用程序提供支持。
Spring Colud Config 作为 Spring Cloud 中不可缺少的一份子,拥有以下核心功能:
接下来,我们就一一讲解以上特性。
Spring Cloud Config 支持将配置文件存放在以下环境:
使用 Spring Cloud Config 管理配置文件,使配置文件与具体应用程序分离,有助于更加清晰对项目进行管理。
下面,通过Spring Cloud Config的主要功能以及代码实现来了解并掌握Spring Cloud Config的基本使用。
Spring Cloud Config 是对多环境配置文件进行统一管理,我们先把配置文件准备好。在目前开发中,我们使用最多的肯定是Git作为版本管理,Spring Cloud Config默认也使用Git进行配置文件的版本管理。
新建一个配置文件存放的仓库,选择有很多:Github、Gitlab、码云,按自己喜欢选 择即可。
创建好仓库后,我们以开发中常见的4中环境(dev、test、pre、prod)作为例子,创建以下4个不同环境的配置文件并提交到仓库。
本文为了测试简单方便,只加入了一个name配置,不同环境显示不同name值。
mimosa-dev.properties
name=dev
mimosa-test.properties
name=test
mimosa-pre.properties
name=pre
mimosa-prod.properties
name=prod
Config Server 是管理配置文件并对外提供配置文件的地方。
除了强制指定使用Maven外,所有项目我都使用Gradle,配置更简单、明了。
较之于Maven或者Ant的XML配置脚本,Gradle使用的Grovvy脚本杀伤力太大了,爱美之心,人皆有之,相比于七旬老妇松松垮垮的皱纹,大家肯定都喜欢少女紧致的脸蛋,XML就是那老妇的皱纹。(引用至Gradle,构建工具的未来?)
group 'me.lyinlong.mimosa'
version '1.0-SNAPSHOT'
repositories {
maven {
url 'https://repo.spring.io/libs-snapshot'
}
}
buildscript {
ext {
springBootVersion = '2.0.0.M3'
}
repositories {
mavenCentral()
maven{url 'https://repo.spring.io/libs-snapshot'}
maven{ url 'https://repo.spring.io/snapshot' }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: "io.spring.dependency-management"
dependencyManagement {
imports {
mavenBom ':spring-cloud-dependencies:Finchley.BUILD-SNAPSHOT'
}
}
dependencies {
compile group: 'org.springframework.cloud', name: 'spring-cloud-config-server', version: '2.0.0.M2'
}
repositories {
maven { url 'https://repo.spring.io/libs-snapshot' }
maven{ url 'https://repo.spring.io/snapshot' }
}
在项目的resources目录新建:application.yml 文件并写入以下内容,如果创建的仓库是公共的,可以删除 username 和 password 配置项。 当然,如果你觉得直接使用密码不是你的做事风格,我们也可以使用ssh方式:只需要将uri改为具体的ssh风格地址。(使用SSH可能会遇到的问题 , 更详细的SSH配置 )
spring:
cloud:
config:
server:
git:
uri: https://github.com/eightpigs/spring-cloud-config-repo.git
username: admin
password: 123
application:
name: config-server
server:
port: 8888
Spring Boot以开箱即用为理念,在配置好Gradle引入配置之后,只需添加一个启动类并添加好相应的注解即可。使用@EnableConfigServer
启用Spring Config Server。
package me.lyinlong.mimosa;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@EnableConfigServer
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
以上配置正确后,供配置中心正常运行的配置项就已经完全写完了。访问 http://localhost:8888/mimosa/dev/ 即可得到Spring Cloud Config转换后的配置内容:
{
"name": "mimosa",
"profiles": ["dev"],
"label": null,
"version": "4d1561220245ab2ed56a6a39a070e16c5cd20ea4",
"state": null,
"propertySources": [{
"name": "github:eightpigs/spring-cloud-config-repo.git/mimosa-dev.properties",
"source": {
"name": "dev"
}
}]
}
其中:propertySources.source 部分就是刚刚我们配置文件的具体内容。
当然,如果你想更获取精简的内容,你可以直接使用文件名访问 http://localhost:8888/mimosa-dev.properties 得到的内容将会是这样的:
name: dev
带着成功的喜悦,我们接下来好好看看其中的一些细节和其他特性。
启动Config Server之后,在不停止项目的情况下,修改 mimosa-dev.properties 配置文件:
name=dev
intro=这是开发环境的配置
刷新页面看看内容是不是也实时变化了?通过Config Server 的实时更新特性,大大降低了以前更动配置文件必须重启系统的次数。
Spring Cloud Config 在对应多系统多环境的情况下,提供以下占位符,增加系统的灵活性:
{application} 应用名称占位符
{profile} 可以理解为一个项目的附属信息占位,可以用于对应用程序的环境区分(dev、test、prod等)
{label} 可选的git标签,可以是git的commit id、分支名、和标签
配置中心是对其他应用程序提供配置服务,每个配置信息应该要标识出属于哪个应用、属于应用的哪个环境,所以不难理解 {application} 和 {profile} 的具体作用。当然,{profile} 不一定是作为应用部署环境的标识,在上面也说明了,{profile} 可以理解为应用程序的附属信息,你可以用它来标识任何内容。
因为统一配置中心是对其他应用程序提供服务的,所以在资源请求方面制定了非常清晰的规范(Web接口的访问形式):
其中,yml 和 properties 的各两种方式是一样的,这是因为Spring Boot开始,配置文件就只有 properties 和 yml 两种格式。所以,不同的资源格式排除资源的扩展名后只有3种。
我更为推荐使用第一种方式,除了提供更多信息供程序处理外,该资源的访问形式也是更加清晰明了,因为我们使用 Config Server 之后,并不是特别关心资源的文件格式,最终的返回内容格式都是一致的。
回过头看看之前为了获取精简内容而使用的方式,是不是能够对应上。
模式匹配使用pattern配置项进行配置。我们来看看官方的例子:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
repos:
simple: https://github.com/simple/config-repo
special:
pattern: special*/dev*,*special*/dev*
uri: https://github.com/special/config-repo
local:
pattern: local*
uri: file:/home/configsvc/config-repo
我们先理解一下模式匹配的基本规则:
pattern 配置项的内容是通配符 与 {application} 和 {profile} 组合的一组匹配规则,将调用配置中心的应用程序(调用方 / config client)与具体仓库匹配起来。如果调用方的 {application} 与定义的仓库模式没有一个匹配上,则使用默认的仓库地址,也就是 spring.cloud.config.server.git.uri
知道了上面的基本规则,很好理解上面3个仓库的匹配模式:
simple 仅匹配 {application} 为 simple 的调用方
special 匹配 {application} 以 “special” 开头 或者 {application} 包含 “special” 和 {profile} 以 “dev” 开头 的调用方
local 匹配 {application} 以 “local” 开头的所有调用方
以上的pattern的内容可以使用YAML数组语法改写为一下样子:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
repos:
special:
pattern:
- 'special*/dev*'
- '*special*/dev*'
uri: https://github.com/special/config-repo
推荐使用YAML数组的形式,配置文件的结果更清晰。
spring:
cloud:
config:
server:
git:
uri: https://github.com/eightpigs/spring-cloud-config-repo.git
clone-on-start: true
application:
name: config-server
server:
port: 8888
可以看到在上面的配置中,使用了 clone-on-start 配置项,该配置项的作用是在启动是就克隆仓库信息,可以实现在启动是检测配置的仓库是否能够正常访问。
如果是一个不可访问的仓库,系统将无法正常系统。
如果没有使用该配置项,仓库将会在被首次请求时克隆。
Spring Cloud Config Server 可以很方便与同系的 spring security
集成。只需要在添加在gradle中添加引入 spring-boot-starter-security
依赖并在 application.yml
中加入以下代码:
security:
user:
name: root
password: root
然后打开浏览器访问,即可看到需要输入用户名、密码的效果了。