spring boot版本为:2.5.6
spring cloud版本为:2020.0.4
前言
Spring Cloud Config为分布式系统外部化配置提供了服务器端和客户端的支持,它包括Config Server和Config Client两部分。由于Config Server和Config Client都实现了对Spring Environment和PropertySource抽象的映射,因此,Spring Cloud Config非常适合Spring应用程序,当然也可与任何其他语言编写的应用程序配合使用。
Config Server是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,默认使用Git存储配置内容(也可使用Subversion、MySQL、本地文件系统或Vault存储配置,本篇以Git为主进行讲解),因此可以很方便地实现对配置的版本控制与内容审计。
Config Client是Config Server的客户端,用于操作存储在Config Server中的配置属性。引入Spring Cloud Config后的架构如下:
config server快速入门
准备配置文件
在git仓库https://gitee.com/lvyq987329931/config-server.git中新建几个配置文件,例如:
ms-foo.properties
ms-foo-dev.properties
ms-foo-test.properties
ms-foo-prod.properties
内容分别是:
profile=default
profile=dev
profile=test
profile=prod
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
编写启动类,添加@EnableConfigServer注解
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
编写配置文件application.yml
server:
port: 8080
spring:
application:
name: ms-config-server
cloud:
config:
server:
git:
uri: https://gitee.com/lvyq987329931/config-server.git
username: git用户名
password: git密码
这样一个config server就完成了
路径规则
Spring Cloud Config Server提供了RESTful API,可用来访问存放在Git仓库中的配置文件。
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
其中的{appliation}、{profile}、{label} 都是占位符。
{appliation}:映射客户端的spring.application.name属性
{profile}:映射客户端的spring.profiles.active属性
{label}:默认映射master分支
按照以上规则,对于本例,可以使用以下url访问到git仓库master分支的ms-foo-dev.properties文件,例如:
http://ocalhost:8080/ms-foo/dev
http://ocalhost:8080/ms-foo-dev.properties
http://ocalhost:8080/master/ms-foo-dev.properties
Spring Cloud Config Server配置详解
git作为后端配置存储
跳过SSL证书验证
禁用配置服务器对Git服务器SSL证书的验证
spring:
cloud:
config:
server:
git:
uri: https://gitee.com/lvyq987329931/config-server.git
username: git用户名
password: git密码
# 默认为false
skip-ssl-validation: true
设置HTTP连接超时
spring:
cloud:
config:
server:
git:
uri: https://example.com/my/repo
# 默认5秒
timeout: 4
占位符
Spring Cloud Config Server支持git存储库URL带有{application}和{profile}(如果需要的话还有{label})占位符,但是请记住该标签始终用作git标签。
spring:
cloud:
config:
server:
git:
uri: https://github.com/myorg/{application}
使用这种方式,即可轻松支持一个应用对应一个Git仓库。同理,也可支持一个profile对应一个Git仓库。
此外,在{application}参数中使用特殊字符串“(_)”可以启用对多个组织的支持,如以下示例所示:
spring:
cloud:
config:
server:
git:
uri: https://github.com/{application}
其中在请求时以以下格式提供{application}:organization(_)application。
模式匹配和多存储库
Spring Cloud Config还支持对应用名称和配置文件名称进行模式匹配,来应对更复杂的需求。模式匹配是一个以逗号分隔的带有通配符的{application}/{profile}
名称列表(注意,以通配符开头的模式可能需要用引号括起来):
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
如果{application}/{profile}
不匹配任何模式,它将使用spring.cloud.config.server.git.uri
下定义的默认URI。在上面的示例中,对于“simple”
存储库,模式是simple/*
(它只匹配所有配置文件中名为simple的应用程序)。“local”
存储库匹配所有配置文件中以local
开头的应用名称
(/*后缀会自动添加到没有配置文件匹配器的任何模式中)。
例如:请求的地址为http://localhost:8080/simple/dev,将匹配simple库
上例中的pattern属性实际上是一个数组,因此您可以使用YAML数组(或属性文件中的[0],[1]等后缀)绑定到多个模式。如果要运行具有多个配置文件的应用程序,则可能需要这样做,如以下示例所示:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
repos:
development:
pattern:
- '*/development'
- '*/staging'
uri: https://github.com/development/config-repo
staging:
pattern:
- '*/qa'
- '*/production'
uri: https://github.com/staging/config-repo
很多场景下,我们可能把配置文件放在了Git仓库子目录中,此时可以使用search-paths指定,search-path同样支持占位符。
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
search-paths:
- foo
- bar*
这样,Config Server就会在Git仓库根目录、foo子目录、以及所有以bar开始的子目录中查找配置文件。
默认情况下,在配置被首次请求时,Config Server才会clone Git仓库。我们也可让Config Server在启动时就clone Git仓库,例如。
spring:
cloud:
config:
server:
git:
uri: https://git/common/config-repo.git
repos:
team-a:
pattern: team-a-*
cloneOnStart: true
uri: https://git/team-a/config-repo.git
team-b:
pattern: team-b-*
cloneOnStart: false
uri: https://git/team-b/config-repo.git
team-c:
pattern: team-c-*
uri: https://git/team-a/config-repo.git
在上面的示例中,服务器在启动时并且在接受任何请求之前克隆team-a的config-repo。在请求其它配置之前,不会克隆存储库
设置在Config Server启动时克隆存储库有助于在Config Server启动时快速识别配置错误的配置源(例如无效的存储库URI)。在没有为配置源启用cloneOnStart的情况下,Config Server可能会以配置错误或无效的配置源成功启动,并且直到应用程序从该配置源请求配置时才检测到错误。
强制拉取Git Repositories
如前所述,Spring Cloud Config服务器会复制远程git存储库,以防本地副本变脏(例如,操作系统进程更改了文件夹内容),使得Spring Cloud Config服务器无法从远程更新本地副本。
要解决此问题,有一个force-pull属性,如果本地副本脏了,则可以使Spring Cloud Config服务器强制从远程存储库强制拉取配置,如以下示例所示:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
force-pull: true
如果有多个存储库配置,则可以为每个存储库配置force-pull属性,如以下示例所示:
spring:
cloud:
config:
server:
git:
uri: https://git/common/config-repo.git
force-pull: true
repos:
team-a:
pattern: team-a-*
uri: https://git/team-a/config-repo.git
force-pull: true
team-b:
pattern: team-b-*
uri: https://git/team-b/config-repo.git
force-pull: true
team-c:
pattern: team-c-*
uri: https://git/team-a/config-repo.git
force-pull属性的默认值为false。
删除Git Repositories中未跟踪的分支
由于Spring Cloud Config Server在本地有一个从远程git存储库克隆的分支副本,因此它将永久保留该分支,直到下一个服务器重新启动(这将创建新的本地存储库)。因此,可能会出现这样的情况:远程分支已被删除,但它的本地副本仍可用于获取。而且,如果Spring Cloud Config Server Client服务以--spring.cloud.config.label=deletedRemoteBranch,master开头,它将从deletedRemoteBranch本地分支获取属性,而不是从master获取属性。
为了保持本地存储库分支的干净并与远程保持一致,可以设置deleteUntrackedBranches属性。它将使Spring Cloud Config Server强制从本地存储库删除未跟踪的分支。例子:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
deleteUntrackedBranches: true
deleteUntrackedBranches属性的默认值为false。
Git刷新率
您可以使用spring.cloud.config.server.git.refreshRate控制config server多久从Git获取更新的配置数据。以秒为单位指定此属性的值。默认情况下,该值为0,这意味着config server将在每次请求时从Git存储库中获取更新的配置。
以版本控制系统作为文件系统的使用
使用基于VCS的后端存储库(git,svn),文件被检出或克隆到本地文件系统。默认情况下,它们以config-repo-
为前缀放在系统临时目录中。例如,在Linux上,它可能是/tmp/config-repo-<randomid>
。一些操作系统通常会清除临时目录。这可能导致意外行为,例如缺少属性。为避免此问题,请通过将spring.cloud.config.server.git.basedir
或spring.cloud.config.server.svn.basedir
设置来更改本地文件存储目录
本地文件系统作为存储库
Config Server中还有一个“native”
配置文件,该配置文件不使用Git,而是从本地类路径或文件系统(您要使用spring.cloud.config.server.native.searchLocations
指向的任何静态URL)加载配置文件。要使用本地配置文件,请使用spring.profiles.active=native
启动Config Server。
记住对本地文件资源使用
file:
前缀(没有前缀的默认情况通常是类路径)。与任何Spring Boot配置一样,您可以嵌入${}
风格的环境占位符,但请记住,Windows中的绝对路径需要额外的/
(例如,file:///${user.home}/config-repo)。
searchLocations的默认值与Spring Boot应用程序(即[
classpath:/, classpath:/config, file:./, file:./config
])相同。这不会将application.properties从服务器发送到所有客户端,因为服务器中存在的任何属性源在发送到客户端之前都会被删除。
本地文件系统后端非常适合快速入门和测试。要在生产环境中使用它,您需要确保文件系统可靠并且可以在Config Server的所有实例之间共享。
搜索位置可以包含{application}、{profile}和{label}的占位符。通过这种方式,您可以隔离路径中的目录,并选择对您有意义的策略(例如每个application的子目录或每个profile文件的子目录)。
如果在searchLocations不使用占位符,默认情况下会自动在搜索路径后面追加{label}。例如,file:/tmp/config与file:/tmp/config/{label}相同。可以通过设置spring.cloud.config.server.native.addLabelLocations=false
来禁用此行为。
经过测试:路径名必须以/结尾,例如:file:/tmp/config/
使用jdbc作为后端存储库
Spring Cloud Config Server支持JDBC(关系数据库)作为配置属性的后端。您可以通过将spring-jdbc
添加到类路径并使用jdbc配置文件或通过添加类型为JdbcEnvironmentRepository的bean来启用该特性。如果在类路径中包含正确的依赖项(有关这方面的更多细节,请参阅用户指南),Spring Boot将自动配置一个数据源。
您可以通过将spring.cloud.config.server.jdbc.enabled
属性设置为false
来禁用jdbcenvirmentrepository的自动配置。
数据库需要有一个名为PROPERTIES的表,该表具有名为APPLICATION,PROFILE和LABEL的列,以及KEY和VALUE。Java中所有字段的类型均为String,因此您可以根据需要将它们设置为VARCHAR。Property值的行为与来自名为{application}-{profile}.properties的Spring Boot属性文件的值的行为相同,加解密相关配置,不在数据库中存储。
redis作为后端存储库
Spring Cloud Config Server支持Redis作为配置属性的后端。你可以通过在Spring Data Redis中添加一个依赖项来启用这个特性。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
下面的配置使用Spring Data RedisTemplate来访问Redis。我们可以用spring.redis.*属性覆盖默认的连接设置。
spring:
profiles:
active: redis
redis:
host: redis
port: 16379
属性应该存储为散列中的字段。hash的名称应该与spring.application.name属性或spring.application.name和spring.profiles.active[n]的组合相同。
HMSET sample-app server.port "8100" sample.topic.name "test" test.property1 "property1"
sample-app等于应用名,当没有指定profile时,将使用default值。
运行命令可以看到上面的哈希应该包含以下键值:
HGETALL sample-app
{
"server.port": "8100",
"sample.topic.name": "test",
"test.property1": "property1"
}
组合多环境存储库
在某些场景中,您可能希望从多个环境存储库提取配置数据。为此,您可以在config server的application.properties或application.yml文件中启用composite 配置文件。例如,如果你想从Subversion存储库和两个Git存储库提取配置数据,你可以为你的配置服务器设置以下属性:
spring:
profiles:
active: composite
cloud:
config:
server:
composite:
-
type: svn
uri: file:///path/to/svn/repo
-
type: git
uri: file:///path/to/rex/git/repo
-
type: git
uri: file:///path/to/walter/git/repo
使用此配置,优先级由composite键下列出的存储库的顺序决定。在上面的示例中,Subversion存储库首先列出,因此在Subversion存储库中相同属性的值将覆盖Git存储库中的值。在rex Git存储库中相同属性的值将覆盖walter Git存储库中的值。
如果只希望从不同类型的存储库提取配置数据,可以在config server的appilication的properties或YAML文件中启用相应的配置,而不是composite配置。例如,如果您想从单个Git存储库和单个HashiCorp Vault服务器提取配置数据,您可以为您的配置服务器设置以下属性:
spring:
profiles:
active: git, vault
cloud:
config:
server:
git:
uri: file:///path/to/git/repo
order: 2
vault:
host: 127.0.0.1
port: 8200
order: 1
使用此配置,优先级可以由order属性确定。可以使用order属性指定所有存储库的优先级顺序。order属性的数值越低,其优先级越高。存储库的优先级顺序有助于解决包含相同属性的存储库之间的任何潜在冲突
如果您的组合环境包括上一个示例中的Vault服务器,则在对配置服务器的每个请求中都必须包含Vault令牌。请参阅Vault后端。
当从Environment Repositories检索值时,任何类型的失败都会导致整个组合环境的失败。如果您希望即使在存储库失败时仍然继续该组合,您可以将spring.cloud.config.server.failOnCompositeError设置为false
在使用组合环境时,重要的是所有存储库都包含相同的labels。如果您有与前面示例中类似的环境,并且请求带有master标签的配置数据时,但Subversion存储库不包含名为master的分支,那么整个请求将失败。
定制组合environment repositories
除了使用Spring Cloud中提供的一个environment repositories之外,您还可以提供自己的EnvironmentRepository bean作为composite environment的一部分。为此,您的bean必须实现EnvironmentRepository接口。如果要在composite environment中控制自定义EnvironmentRepository的优先级,则还应该实现Ordered接口并覆盖getOrdered方法。如果未实现Ordered接口,则EnvironmentRepository的优先级最低。
属性覆盖
config server有一个“overrides”
特性,允许操作人员为所有应用程序提供配置属性。常规的Spring Boot应用程序不能更改被覆盖的属性。要声明覆盖,请将名称-值对的映射添加到spring.cloud.config.server.overrides
,如下面的示例所示:
spring:
cloud:
config:
server:
overrides:
foo: bar
上面的例子导致所有config客户端的应用程序读取foo=bar,独立于它们自己的配置。
配置系统不应该提供属性覆盖。但是,它们确实为Spring Cloud Config客户端提供了有用的默认行为。
通常使用
${}
的Spring环境占位符可以使用反斜杠(“\”)来转义(并在客户端上解析)来转义“$”或“{”
,例如\${app.foo:bar}
解析为“bar “
除非该应用程序提供自己的”app.foo“
。
这句话怎么理解呢?比如上面的
foo
属性,可以以这种方式表达foo: ${app.foo:bar}
,在客户端没有提供app.foo
属性时,默认为bar
。如果客户端在配置文件中提供了这个属性,需要配合下面的overrideNone=true
属性,并在环境变量或系统属性中提供:--foo=${app.foo}
在YAML中,不需要转义反斜杠本身。但是,在属性文件中,当您在服务器上配置覆盖时,确实需要转义反斜杠
config client想要更改这种默认行为,可以通过在远程配置文件中设置spring.cloud.config.overrideNone=true
(默认为false),然后在客户端环境变量或系统属性中提供自己的值:例如:--foo=baz
健康指标
config server附带一个运行状况指标,用于检查配置的环境存储库是否正常工作。默认情况下,它向EnvironmentRepository请求application=app、profile=default和EnvironmentRepository实现提供的默认标签。
您可以配置运行状况指标以检查更多应用程序以及自定义配置文件和自定义标签,如下面的示例所示:
spring:
cloud:
config:
server:
health:
repositories:
myservice:
label: mylabel
myservice-dev:
name: myservice
profiles: development
可以通过设置spring.cloud.config.server.health.enabled=false
禁用运行状况指标。
最新版的官方文档中指示通过
management.health.config.enabled=false
来禁用健康指标,但是经测试,并不好使。
默认情况下请求
/actuator/health
端点,只返回status字段,如需更多详细信息需配置management.endpoint.health.show-details=always
安全性
您可以以任何对您有意义的方式保护配置服务器(从物理网络安全到OAuth2承载令牌),Spring security和Spring Boot提供了许多安全方面的支持。
要使用缺省的Spring boot配置的HTTP Basic安全性,请在类路径上包括Spring security(例如,通过Spring boot-starter-security)。默认的用户名为user和随机生成的密码。随机密码在实践中并不实用,所以我们建议您配置密码(通过设置spring.security.user.password)并加密它(参见下面的说明如何做到这一点)。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
spring:
security:
user:
name: user
password: 111
此时访问config server,就会看到如下的登录页面:
欢迎关注我的公众号:程序员L札记