文章目录
写在前面
该文参考来自 程序猿DD 的Spring Cloud 微服务实战一书,该文是作为阅读了
spring cloud config
一章的读书笔记。书中版本比较老,我选择了最新稳定版的spring cloud Greenwich.SR2
版本,该版本较书中版本有些变动。非常感谢作者提供了这么好的学习思路,谢谢!文章也参考了Spring-cloud-config
的官方文档。
1. Environment 库
配置服务器的配置数据存储在哪里? 管理这种行为的策略是 EnvironmentRepository
,它服务于Environment
对象。该环境是从Spring环境(包括propertySources
作为主要特性)复制域的浅版本。Environment
资源参数化有三个变量:
{application}
映射为客户端的Spring.application.name
{profile}
映射为客户端的spring.profiles.active
(逗号分隔){label}
服务端特性,标记着一些列“版本控制” 文件
存储库实现的行为类似于 Spring boot 程序。从一个等于 spring.config.nmae
的 {application}
参数,加载配置文件。spring.profiles.active
等于 {profiles}
参数。配置文件的优先规则也与常规 Spring boot 应用程序相同:active 配置优先于默认配置。如果有多个配置文件,则最后一个配置文件优先。
下面的示例是一个拥有引导配置的客户端程序:
bootstrap.yml.
spring:
application:
name: foo
profiles:
active: dev,mysql
在基于文件的存储库,服务端将从 application.yml
(所有客户端共享的)和 foo.yml
(foo.yml
优先) 创建一个 Environment
。你可以设置 spring.cloud.config.server.accept-empty
变为 false,这样如果没有找到应用程序,服务器将返回 HTTP 404状态。默认情况下,此标志设置为true。
1.1 Git 后端
前文创建的快速开始就是基于 Git 后端的,现在再来详细探讨下。
EnvironmentRepository
的默认实现使用 Git 后端,这对于管理升级和物理环境以及审计更改非常方便。要更改存储库的位置,可以设置服务端(例如application.yml)的spring.cloud.config.server.git.uri
配置属性。如果您使用file:
前缀设置它,那么它可以在本地存储库中工作,这样您就可以在没有服务器的情况下快速轻松地启动它。但是,在这种情况下,服务器直接操作本地存储库,而不进行克隆(从远程git
库clone
)。为了扩展配置服务器并使其具有高可用性,需要让服务器的所有实例都指向同一个存储库,这样只有共享的文件系统才能工作。即使在这种情况下,最好使用共享文件系统存储库的ssh:协议,以便服务器可以克隆它并使用本地工作副本作为缓存。
跳过 SSL 中心认证
在前一篇博文中,我们使用了 spring.cloud.config.server.git.skipSslValidation
属性,该属性是用于禁用配置服务器对 git
服务器的 SSL 证书的验证。
设置HTTP 连接超时
使用 spring.cloud.config.server.git.timeout
属性, 配置服务器等待获取 HTTP 连接的时间(以秒为单位)。
模式匹配和多仓库
Spring Cloud 配置还支持对应用程序和配置文件名称进行模式匹配的更复杂需求。模式格式是一个逗号分隔的带有通配符的{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
开头的所有应用程序名称(/*
后缀自动添加到没有配置文件匹配器的任何模式中)。
每个存储库还可以选择将配置文件存储在子目录中,搜索这些目录的模式可以指定为searchPaths
。下面的例子展示了顶层的配置文件:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
searchPaths: foo,bar*
在前面的示例中,服务器在顶层和foo/
子目录中搜索配置文件,以及名称以bar开头的任何子目录。
默认情况下,服务器在首次请求配置时克隆远程存储库。服务器可以配置为在启动时克隆存储库:
spring:
cloud:
config:
server:
git:
clone-on-start: true
在配置服务器启动时设置要克隆的存储库有助于在配置服务器启动时快速识别配置错误的配置源。
Git 刷新速率
通过使用spring.cloud.config.server.git.refreshRate
,可以控制配置服务器从Git后端获取更新配置数据的频率。此属性的值以秒为单位指定。默认值为0,这意味着每次请求配置服务器时,配置服务器都会从Git repo
获取更新后的配置。
1.2 版本控制后端文件系统的使用
使用基于vcs
(版本控制后端)的后端(git
、svn
),文件被检出或克隆到本地文件系统。默认情况下,它们被放在系统临时目录中,前缀为config-repo-
。例如,在linux
上,它可以是/tmp/config-repo-<randomid>
。一些操作系统经常清理临时目录。这可能导致意外的行为,比如丢失属性。为了避免这个问题,可以通过设置spring.cloud.config.server.git.basedir
或spring.cloud.config.server.svn.basedir
来更改Config Server
使用不驻留在系统临时结构中的目录。
1.3 文件系统后端
在配置服务端提供了一种从文件系统或者当前类路径下加载配置文件的方式,我们只需要配置 spring.profiles.active=native
,我们可以通过 spring.cloud.config.server.native.searchLocations
来指定具体的配置文件位置。
searchLocations
的默认值与本地Spring启动应用程序相同(即[classpath:/, classpath:/config, file:./,file:./config)。这不会公开application.properties
。因为服务器中存在的任何属性源在发送到客户端之前都会被删除。
1.4 JDBC 后端
Spring Cloud Config Server
支持JDBC
(关系数据库)作为配置属性的后端。您可以通过向类路径添加spring-jdbc
并使用jdbc
配置文件或通过添加类型为JdbcEnvironmentRepository
的bean来启用此功能。如果您在类路径中包含了正确的依赖项(有关详细信息,请参阅用户指南),Spring Boot将配置一个数据源。
数据库需要有一个名为PROPERTIES
的表,其中的列称为APPLICATION
、PROFILE
和LABEL
(与通常的环境含义相同),以及PROPERTIES
风格的键和值对的key
和value
。在Java
中,所有字段的类型都是String
,因此您可以使它们成为任意长度的VARCHAR
。属性值的行为与它们来自名为{application}-{profile}
的Spring引导属性文件时的行为相同。属性,包括所有的加密和解密,它们将作为后处理步骤应用(也就是说,不是直接在存储库中实现)。
分析 JdbcEnvironmentRepository
类,发现其只有一个构造函数:
public JdbcEnvironmentRepository(JdbcTemplate jdbc,
JdbcEnvironmentProperties properties) {
this.jdbc = jdbc;
this.order = properties.getOrder();
this.sql = properties.getSql();
}
也就是说我们自己构造 JdbcEnvironmentRepository bean
的话,我们需要一个 JdbcEnvironmentProperties
对象,那么Spring cloud 是否有基于 jdbc 作为后端的自动呢?按以上的描述来看,确实有,并且我们只需要在类路径下添加spring-jdbc
,即可启用自动配置。
通过 JdbcEnvironmentRepository
定位到源码,查看包的结构,找到 config
(配置类一般都会在这里)。找到 JdbcRepositoryConfiguration
:
@Configuration
@Profile("jdbc")
@ConditionalOnClass(JdbcTemplate.class)
class JdbcRepositoryConfiguration {
@Bean
@ConditionalOnBean(JdbcTemplate.class)
public JdbcEnvironmentRepository jdbcEnvironmentRepository(
JdbcEnvironmentRepositoryFactory factory,
JdbcEnvironmentProperties environmentProperties) {
return factory.build(environmentProperties);
}
}
以及它的工厂类:
@Configuration
@ConditionalOnClass(JdbcTemplate.class)
static class JdbcFactoryConfig {
@Bean
@ConditionalOnBean(JdbcTemplate.class)
public JdbcEnvironmentRepositoryFactory jdbcEnvironmentRepositoryFactory(
JdbcTemplate jdbc) {
return new JdbcEnvironmentRepositoryFactory(jdbc);
}
}
这证明上述的分析是正确的,JdbcTemplate
存在的情况下,我们无需手动创建 Bean,并且,我们可以通过 JdbcEnvironmentProperties
中声明的属性在配置文件中更改默认的配置(包括自定义如何从数据库中查询key-value
对的sql
语句)。
1.5 组合式后端
在某些场景中,您可能希望从多个环境存储库提取配置数据。为此,您可以在配置服务器的应用程序属性或YAML
文件中启用组合配置文件。例如,如果希望从一个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
使用此配置,优先级由组合键下存储库的列出顺序决定。在上面的示例中,首先列出了Subversion
存储库,因此在Subversion
存储库中找到的值将覆盖其中一个Git
存储库中为相同属性找到的值。在rex
Git存储库中找到的值将先于在walter
Git存储库中找到的相同属性的值。
如果只想从不同类型的存储库中提取配置数据,可以在配置服务器的应用程序属性或YAML
文件中启用相应的配置文件,而不是复合配置文件。例如,如果希望从单个Git存储库和单个svn
存储库提取配置数据,可以为配置服务器设置以下属性:
spring:
profiles:
active: git, vault
cloud:
config:
server:
git:
uri: file:///path/to/git/repo
order: 2
svn:
uri: file:///path/to/svn/repo
order: 1
使用此配置,可以通过order属性确定优先级。可以使用order属性指定所有存储库的优先级顺序。阶属性的数值越低,优先级越高。存储库的优先级顺序有助于解决包含相同属性值的存储库之间的任何潜在冲突。
1.6 属性重载
配置服务器有一个 “overrides” 特性,允许操作员为所有应用程序提供配置属性。被覆盖的属性不能被应用程序使用普通的Spring引导挂钩意外地更改。要声明覆盖,请将名称-值对映射添加到spring.cloud.config.server.overrides
,如下例所示:
spring:
cloud:
config:
server:
overrides:
foo: bar
这将导致所有配置客户端应用程序读取foo=bar
,独立于它们自己的配置。
2. 健康监测
配置服务器附带一个健康指示器,用于检查配置的环境存储库是否工作。默认情况下,它会向环境存储库请求一个名为app
的应用程序、default
profile 和默认label
。
您可以配置健康指示器来检查更多的应用程序以及自定义配置文件和自定义标签,如下面的示例所示:
spring:
cloud:
config:
server:
health:
repositories:
myservice:
label: mylabel
myservice-dev:
name: myservice
profiles: development
也可以通过 spring.cloud.config.server.health.enabled=false
来禁用健康监测。
3. 安全访问
您可以以任何对您有意义的方式保护您的配置服务器(从物理网络安全到OAuth2
承载令牌),因为Spring security
和Spring Boot
为许多安全安排提供了支持。
要使用默认的Spring启动配置的HTTP基本安全性,请在类路径中包含Spring Security
(例如,通过spring-boot-starter-security
)。默认是user
的用户名和随机生成的密码(这可以通过启动时的控制台日志查看)。随机密码在实践中并不有用,因此我们建议您配置密码(通过设置spring.security.user.password
)并对其进行加密(有关如何进行加密的说明,请参阅下面的说明)。
有关加密和解密,我了解的并不多,留下文档地址。
4. 高可用配置
spring cloud 实现服务端的高可用非常简单,主要有以下两种方式。
- 传统模式:不需要为这些服务端做额外的配置,只需要遵守一个配置规则,将所有的
config server
都指向同一个Git
仓库,这样所有的配置内容就通过统一的共享文件系统来维护。而客户端在指定Config Server
位置时,只需要配置Config Server
上层的负载均衡设备地址即可。 - 服务模式:我们仍可以将
Config Server
作为一个普通的微服务应用,纳入Eureka
的服务治理体系中。这样微服务应用就可以通过配置中心的服务名来获取配置信息。不过这部分实现需要客户端配合。
以上内容摘抄自 DD的 Spring Cloud 微服务实战一书