Spring Cloud Config服务器
服务器为外部配置(名称值对或等效的YAML内容)提供了基于资源的HTTP。服务器可以使用@EnableConfigServer注释轻松嵌入到Spring Boot应用程序中。所以这个应用程序是一个配置服务器:
ConfigServer.java
@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
public static void main(String[] args) {
SpringApplication.run(ConfigServer.class, args);
}
}
像所有的默认端口8080上运行的所有Spring Boot应用程序一样,但您可以通过各种方式将其切换到常规端口8888。最简单的也是设置一个默认配置库,它是通过启动它的spring.config.name=configserver(在Config Server jar中有一个configserver.yml)。另一个是使用你自己的application.properties,例如
application.properties
server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo
其中${user.home}/config-repo是包含YAML和属性文件的git仓库。
注意 | 在Windows中,如果文件URL为绝对驱动器前缀,例如file:///${user.home}/config-repo,则需要额外的“/”。 |
---|
提示 | 以下是上面示例中创建git仓库的方法: |
---|
$ cd $HOME
$ mkdir config-repo
$ cd config-repo
$ git init .
$ echo info.foo: bar > application.properties
$ git add -A .
$ git commit -m "Add application.properties"
警告 | 使用本地文件系统进行git存储库仅用于测试。使用服务器在生产环境中托管配置库。 |
---|
警告 | 如果您只保留文本文件,则配置库的初始克隆将会快速有效。如果您开始存储二进制文件,尤其是较大的文件,则可能会遇到服务器中第一个配置请求和/或内存不足错误的延迟。 |
---|
环境库
您要在哪里存储配置服务器的配置数据?管理此行为的策略是EnvironmentRepository,服务于Environment对象。此Environment是Spring Environment(包括propertySources作为主要功能)的域的浅层副本。Environment资源由三个变量参数化:
-
{application}映射到客户端的“spring.application.name”;
-
{profile}映射到客户端上的“spring.profiles.active”(逗号分隔列表); 和
-
{label}这是一个服务器端功能,标记“版本”的配置文件集。
存储库实现通常表现得像一个Spring Boot应用程序从“spring.config.name”等于{application}参数加载配置文件,“spring.profiles.active”等于{profiles}参数。配置文件的优先级规则也与常规启动应用程序相同:活动配置文件优先于默认配置,如果有多个配置文件,则最后一个获胜(例如向Map添加条目)。
示例:客户端应用程序具有此引导配置:
bootstrap.yml
spring:
application:
name: foo
profiles:
active: dev,mysql
(通常使用Spring Boot应用程序,这些属性也可以设置为环境变量或命令行参数)。
如果存储库是基于文件的,则服务器将从application.yml创建Environment(在所有客户端之间共享),foo.yml(以foo.yml优先))。如果YAML文件中有文件指向Spring配置文件,那么应用的优先级更高(按照列出的配置文件的顺序),并且如果存在特定于配置文件的YAML(或属性)文件,那么这些文件也应用于优先级高于默认值。较高优先级转换为Environment之前列出的PropertySource。(这些规则与独立的Spring Boot应用程序相同。)
Git后端
EnvironmentRepository的默认实现使用Git后端,这对于管理升级和物理环境以及审核更改非常方便。要更改存储库的位置,可以在Config Server中设置“spring.cloud.config.server.git.uri”配置属性(例如application.yml)。如果您使用file:前缀进行设置,则应从本地存储库中工作,以便在没有服务器的情况下快速方便地启动,但在这种情况下,服务器将直接在本地存储库上进行操作,而不会克隆如果它不是裸机,因为配置服务器永远不会更改“远程”资源库)。要扩展Config Server并使其高度可用,您需要将服务器的所有实例指向同一个存储库,因此只有共享文件系统才能正常工作。即使在这种情况下,最好使用共享文件系统存储库的ssh:协议,以便服务器可以将其克隆并使用本地工作副本作为缓存。
该存储库实现将HTTP资源的{label}参数映射到git标签(提交ID,分支名称或标签)。如果git分支或标签名称包含斜杠(“/”),则应使用特殊字符串“()”指定HTTP URL中的标签,以避免与其他URL路径模糊。例如,如果标签为foo/bar,则替换斜杠将导致标签看起来像foo()bar。如果您使用像curl这样的命令行客户端(例如使用引号将其从shell中转出来),请小心URL中的方括号。
Git URI中的占位符
Spring Cloud Config服务器支持一个Git仓库URL,其中包含{application}和{profile}(以及{label})的占位符,如果需要,请记住标签应用为git标签)。因此,您可以使用(例如)轻松支持“每个应用程序的一个repo”策略:
spring:
cloud:
config:
server:
git:
uri: https://github.com/myorg/{application}
或使用类似模式但使用{profile}的“每个配置文件一个”策略。
模式匹配和多个存储库
还可以通过应用程序和配置文件名称的模式匹配来支持更复杂的需求。模式格式是带有通配符的{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/(即所有配置文件中只匹配一个名为“简单”的应用程序)。“本地”存储库与所有配置文件中以“local”开头的所有应用程序名称匹配(将/后缀自动添加到任何没有配置文件匹配器的模式)。
注意 | 在上述“简单”示例中使用的“单行”快捷方式只能在唯一要设置的属性为URI的情况下使用。如果您需要设置其他任何内容(凭据,模式等),则需要使用完整的表单。 |
---|
repo中的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
注意 | Spring Cloud将猜测包含不在中的配置文件的模式意味着您实际上要匹配从此模式开始的配置文件列表(因此/staging是["/staging", "/staging,*"])。这是常见的,您需要在本地的“开发”配置文件中运行应用程序,但也可以远程运行“云”配置文件。 |
---|
每个存储库还可以选择将配置文件存储在子目录中,搜索这些目录的模式可以指定为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:
uri: https://git/common/config-repo.git
repos:
team-a:
pattern: team-a-*
cloneOnStart: true
uri: http://git/team-a/config-repo.git
team-b:
pattern: team-b-*
cloneOnStart: false
uri: http://git/team-b/config-repo.git
team-c:
pattern: team-c-*
uri: http://git/team-a/config-repo.git
在此示例中,服务器在启动之前克隆了team-a的config-repo,然后它接受任何请求。所有其他存储库将不被克隆,直到请求从存储库配置。
注意 | 在配置服务器启动时设置要克隆的存储库可以帮助在配置服务器启动时快速识别错误配置的源(例如,无效的存储库URI)。配置源不启用cloneOnStart时,配置服务器可能会成功启动配置错误或无效的配置源,而不会检测到错误,直到应用程序从该配置源请求配置为止。 |
---|
认证
要在远程存储库上使用HTTP基本身份验证,请分别添加“username”和“password”属性(不在URL中),例如
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
username: trolley
password: strongpassword
如果您不使用HTTPS和用户凭据,当您将密钥存储在默认目录(~/.ssh)中,并且uri指向SSH位置时,SSH也应该开箱即用,例如“ git@github.com:配置/云配置”。必须在~/.ssh/known_hosts文件中存在Git服务器的条目,并且它是ssh-rsa格式。其他格式(如ecdsa-sha2-nistp256)不受支持。为了避免意外,您应该确保Git服务器的known_hosts文件中只有一个条目,并且与您提供给配置服务器的URL匹配。如果您在URL中使用了主机名,那么您希望在known_hosts文件中具有这一点,而不是IP。使用JGit访问存储库,因此您发现的任何文档都应适用。HTTPS代理设置可以~/.git/config设置,也可以通过系统属性(-Dhttps.proxyHost和-Dhttps.proxyPort)与任何其他JVM进程相同。
提示 | 如果您不知道~/.git目录使用git config–global来处理设置的位置(例如git config --globalhttp.sslVerify false)。 |
---|
使用AWS CodeCommit进行认证
AWS CodeCommit认证也可以完成。当从命令行使用Git时,AWS CodeCommit使用身份验证助手。该帮助器不与JGit库一起使用,因此如果Git URI与AWS CodeCommit模式匹配,则将创建用于AWS CodeCommit的JGit CredentialProvider。AWS CodeCommit URI始终看起来像
https://git-codecommit.$ {AWS_REGION} .amazonaws.com / $ {repopath}。
如果您使用AWS CodeCommit URI提供用户名和密码,那么这些URI必须
是用于访问存储库的AWS accessKeyId和 secretAccessKey。如果不指定用户名和密码,则将使用AWS默认凭据提供程序链检索accessKeyId和secretAccessKey
。
如果您的Git URI与CodeCommit URI模式(上述)匹配,则必须在用户名和密码或默认凭据提供程序链支持的某个位置中提供有效的AWS凭据。AWS EC2实例可以使用EC2实例的
IAM角色。
注意:aws-java-sdk-core jar是一个可选的依赖关系。如果aws-java-sdk-core jar不在您的类路径上,则无论git服务器URI如何,都将不会创建AWS代码提交凭据提供程序。
Git搜索路径中的占位符
Spring Cloud Config服务器还支持具有{application}和{profile}(以及{label}(如果需要))占位符的搜索路径。例:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
searchPaths: '{application}'
在资源库中搜索与目录(以及顶级)相同名称的文件。通配符在具有占位符的搜索路径中也是有效的(搜索中包含任何匹配的目录)。
力拉入Git存储库
如前所述Spring Cloud Config服务器克隆远程git存储库,如果某种方式本地副本变脏(例如,通过操作系统进程更改文件夹内容),则Spring Cloud Config服务器无法从远程存储库更新本地副本。
要解决这个问题,有一个force-pull属性,如果本地副本是脏的,将使Spring Cloud Config Server强制从远程存储库拉。例:
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: http://git/team-a/config-repo.git
force-pull: true
team-b:
pattern: team-b-*
uri: http://git/team-b/config-repo.git
force-pull: true
team-c:
pattern: team-c-*
uri: http://git/team-a/config-repo.git
注意 | force-pull属性的默认值为false。 |
---|
版本控制后端文件系统使用
警告 | 使用基于VCS的后端(git,svn)文件被检出或克隆到本地文件系统。默认情况下,它们放在系统临时目录中,前缀为config-repo-。在linux上,例如可以是/tmp/config-repo-。一些操作系统会定期清除临时目录。这可能会导致意外的行为,例如缺少属性。为避免此问题,请通过将spring.cloud.config.server.git.basedir或spring.cloud.config.server.svn.basedir设置为不驻留在系统临时结构中的目录来更改Config Server使用的目录。 |
---|
文件系统后端
配置服务器中还有一个不使用Git的“本机”配置文件,只是从本地类路径或文件系统加载配置文件(您想要指向的任何静态URL“spring.cloud.config.server .native.searchLocations“)。要使用本机配置文件,只需使用“spring.profiles.active = native”启动Config Server。
注意 | 请记住使用file:前缀的文件资源(缺省没有前缀通常是classpath)。与任何Spring Boot配置一样,您可以嵌入${}样式的环境占位符,但请记住,Windows中的绝对路径需要额外的“/”,例如file:///${user.home}/config-repo |
---|
警告 | file:./, file:./config])相同。这不会将application.properties从服务器暴露给所有客户端,因为在发送到客户端之前,服务器中存在的任何属性源都将被删除。 |
---|
提示 | 文件系统后端对于快速入门和测试是非常好的。要在生产中使用它,您需要确保文件系统是可靠的,并在配置服务器的所有实例中共享。 |
---|
搜索位置可以包含{application},{profile}和{label}的占位符。以这种方式,您可以隔离路径中的目录,并选择一个有用的策略(例如每个应用程序的子目录或每个配置文件的子目录)。
如果您不在搜索位置使用占位符,则该存储库还将HTTP资源的{label}参数附加到搜索路径上的后缀,因此属性文件将从每个搜索位置加载并具有相同名称的子目录作为标签(标记的属性在Spring环境中优先)。因此,没有占位符的默认行为与添加以/{label}/. For example `file:/tmp/config结尾的搜索位置与file:/tmp/config,file:/tmp/config/{label}相同
Vault后端
Spring Cloud Config服务器还支持Vault作为后端。
Vault是安全访问秘密的工具。一个秘密是你想要严格控制访问的任何东西,如API密钥,密码,证书等等。Vault为任何秘密提供统一的界面,同时提供严格的访问控制和记录详细的审核日志。 |
---|
有关Vault的更多信息,请参阅Vault快速入门指南。
要使配置服务器使用Vault后端,您必须使用vault配置文件运行配置服务器。例如在配置服务器的application.properties中,您可以添加spring.profiles.active=vault。
默认情况下,配置服务器将假定您的Vault服务器正在运行于http://127.0.0.1:8200。它还将假定后端名称为secret,密钥为application。所有这些默认值都可以在配置服务器的application.properties中配置。以下是可配置Vault属性的表。所有属性前缀为spring.cloud.config.server.vault。
名称 | 默认值 |
---|---|
host | 127.0.0.1 |
port | 8200 |
scheme | HTTP |
backend | 秘密 |
defaultKey | 应用 |
profileSeparator | , |
所有可配置的属性可以在org.springframework.cloud.config.server.environment.VaultEnvironmentRepository找到。
运行配置服务器后,可以向服务器发出HTTP请求,以从Vault后端检索值。为此,您需要为Vault服务器创建一个令牌。
首先放置一些数据给你Vault。例如
$ vault write secret/application foo=bar baz=bam
$ vault write secret/myapp foo=myappsbar
现在,将HTTP请求发送给您的配置服务器以检索值。
$ curl -X “GET” “http://localhost:8888/myapp/default” -H “X-Config-Token: yourtoken”
在提出上述要求后,您应该会看到类似的回复。
{
"name":"myapp",
"profiles":[
"default"
],
"label":null,
"version":null,
"state":null,
"propertySources":[
{
"name":"vault:myapp",
"source":{
"foo":"myappsbar"
}
},
{
"name":"vault:application",
"source":{
"baz":"bam",
"foo":"bar"
}
}
]
}
多个Properties来源
使用Vault时,您可以为应用程序提供多个属性源。例如,假设您已将数据写入Vault中的以下路径。
secret/myApp,dev
secret/myApp
secret/application,dev
secret/application
写入secret/application的Properties可
用于使用配置服务器的所有应用程序。名称为myApp的应用程序将具有写入secret/myApp和secret/application的任何属性。当myApp启用dev配置文件时,写入所有上述路径的属性将可用,列表中第一个路径中的属性优先于其他路径。
与所有应用共享配置
基于文件的存储库
使用基于文件(即git,svn和native)的存储库,文件名为application*的资源在所有客户端应用程序(所以application.properties,application.yml,application-*.properties等)之间共享)。您可以使用这些文件名的资源来配置全局默认值,并根据需要将其覆盖应用程序特定的文件。
#_property_overrides [属性覆盖]功能也可用于设置全局默认值,并且允许占位符应用程序在本地覆盖它们。
提示 | 使用“本机”配置文件(本地文件系统后端),建议您使用不属于服务器自身配置的显式搜索位置。否则,默认搜索位置中的application*资源将被删除,因为它们是服务器的一部分。 |
---|
Vault服务器
当使用Vault作为后端时,可以通过将配置放在secret/application中与所有应用程序共享配置。例如,如果您运行此Vault命令
$ vault write secret/application foo=bar baz=bam
使用配置服务器的所有应用程序都可以使用属性foo和baz。
复合环境库
在某些情况下,您可能希望从多个环境存储库中提取配置数据。为此,只需在配置服务器的应用程序属性或YAML文件中启用多个配置文件即可。例如,如果您要从Git存储库以及SVN存储库中提取配置数据,那么您将为配置服务器设置以下属性。
spring:
profiles:
active: git, svn
cloud:
config:
server:
svn:
uri: file:///path/to/svn/repo
order: 2
git:
uri: file:///path/to/git/repo
order: 1
除了指定URI的每个repo之外,还可以指定order属性。order属性允许您指定所有存储库的优先级顺序。order属性的数值越低,优先级越高。存储库的优先顺序将有助于解决包含相同属性的值的存储库之间的任何潜在冲突。
注意 | 从环境仓库检索值时的任何类型的故障将导致整个复合环境的故障。 |
---|
注意 | 当使用复合环境时,重要的是所有repos都包含相同的标签。如果您有类似于上述的环境,并且使用标签master请求配置数据,但是SVN repo不包含称为master的分支,则整个请求将失败。 |
---|
自定义复合环境库
除了使用来自Spring Cloud的环境存储库之外,还可以提供自己的EnvironmentRepository bean作为复合环境的一部分。要做到这一点,你的bean必须实现EnvironmentRepository接口。如果要在复合环境中控制自定义EnvironmentRepository的优先级,您还应该实现Ordered接口并覆盖getOrdered方法。如果您不实现Ordered接口,那么您的EnvironmentRepository将被赋予最低优先级。
属性覆盖
配置服务器具有“覆盖”功能,允许操作员为应用程序使用普通的Spring Boot钩子不会意外更改的所有应用程序提供配置属性。要声明覆盖,只需将名称/值对的地图添加到spring.cloud.config.server.overrides。例如
spring:
cloud:
config:
server:
overrides:
foo: bar
将导致配置客户端的所有应用程序独立于自己的配置读取foo=bar。(当然,应用程序可以以任何方式使用Config Server中的数据,因此覆盖不可强制执行,但如果它们是Spring Cloud Config客户端,则它们确实提供有用的默认行为。)
提示 | 通过使用反斜杠(“\”)来转义“$”或“{”,例如${app.foo:bar}解析,可以转义正常的Spring具有“$ {}”的环境占位符到“bar”,除非应用程序提供自己的“app.foo”。请注意,在YAML中,您不需要转义反斜杠本身,而是在您执行的属性文件中配置服务器上的覆盖。 |
---|
您可以通过在远程存储库中设置标志spring.cloud.config.overrideNone=true(默认为false),将客户端中所有覆盖的优先级更改为更为默认值,允许应用程序在环境变量或系统属性中提供自己的值。
欢迎关注作者的公众号《Java编程生活》,每日记载Java程序猿工作中遇到的问题