Spring Cloud Config
Spring Cloud Config 为分布式服务提供了服务侧和客户侧的外部配置支持. 通过 Spring Cloud Config 你可以有一个统一的地方来管理所有应用的外部配置.
默认服务端存储实现用的是 git, 因此, 它很容易支持配置环境的标签版本, 并且可以访问各种管理内容的工具.
1. Quick Start
此小结将介绍 Spring Cloud Config Server 的客户端和服务端.
首先, 启动服务端:
- $ cd spring-cloud-config-server
- $ ../mvnw spring-boot:run
接着试一下客户端:
- $ curl localhost:8888/foo/development
- {"name":"foo","label":"master","propertySources":[ {"name":"https://github.com/scratches/config-repo/foo-development.properties","source":{"bar":"spam"}},
- {"name":"https://github.com/scratches/config-repo/foo.properties","source":{"foo":"bar"}}
- ]}
默认定位属性资源的策略是使用 git(spring.cloud.config.server.git.uri), 并且用它来初始化一个迷你 SpringApplication, 这个迷你 application 的 Environment 是用来枚举属性资源并将它发布到一个 JSON 端点.
HTTP 服务的格式如下:
- /{application}/{profile}[/{label}]
- /{application}-{profile}.yml
- /{label}/{application}-{profile}.yml
- /{application}-{profile}.properties
- /{label}/{application}-{profile}.properties
其中 application 是是使用 spring.config.name 属性注入的, profile 是一个激活的配置文件(或者是以逗号分隔的属性),label 是一个可选的 git 标签(默认是 master).
Spring Cloud Config Server 从 git 仓库为客户端拉取配置, 如下:
- spring:
- cloud:
- config:
- server:
- git:
- uri: https://github.com/spring-cloud-samples/config-repo
- 1.1 Client Side Usage(客户端用法)
要在一个应用中使用这些特性, 你可以构建一个 Spring Boot application 并且添加 spring-cloud-config-client 相关的依赖, 最方便的方法是添加 org.springframework.cloud:spring-cloud-starter-config 依赖.
下面是一个典型的 maven 配置:
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>{spring-boot-docs-version}</version>
- <relativePath /> <!-- lookup parent from repository -->
- </parent>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-dependencies</artifactId>
- <version>{spring-cloud-version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-config</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
现在可以创建一个标准的 Spring Boot application, 如下:
- @SpringBootApplication
- @RestController
- public class Application {
- @RequestMapping("/")
- public String home() {
- return "Hello World!";
- }
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- }
当这个 HHTP 服务启动时, 它默认从本地的 config server(端口 8888)加载配置, 可以使用 bootstrap.properties 配置来改变这个默认行为:
1 spring.cloud.config.uri: http://myconfigserver.com
可以使用 / env 端点来查看 bootstrap properties 配置:
- $ curl localhost:8080/env
- {
- "profiles":[],
- "configService:https://github.com/spring-cloud-samples/config-repo/bar.properties":{"foo":"bar"},
- "servletContextInitParams":{},
- "systemProperties":{...},
- ...
- }
- 2. Spring Cloud Config Server(配置服务器的服务端)
Spring Cloud Config Server 为外部配置提供一个基于资源的 HTTP API. 使用注解 @EnableConfigServer 可以在一个 Spring Boot application 中嵌入配置服务器. 例如:
- @SpringBootApplication
- @EnableConfigServer
- public class ConfigServer {
- public static void main(String[] args) {
- SpringApplication.run(ConfigServer.class, args);
- }
- }
最简单的方法是通过属性 spring.config.name=configserver 启动, 因为在 config server 的 jar 中有一个 configserver.yml 配置文件, 它已经设置好了默认的配置仓库.
或者你可以使用自己的配置: application.properties
- server.port: 8888
- spring.cloud.config.server.git.uri: file://${user.home}/config-repo
其中 ${user.home}/config-repo 是一个包含 YAML 或者 properties 格式配置文件的 git 仓库.
注意:
1)在 windows 上, 你需要在 file url 前多添加一个 "/", 如果是绝对路径的话.(例如: file:///${user.home}/config-repo)
2)使用本地仓库只是为了演示和测试使用, 在正式环境中需要使用一台服务器来管理配置
3)初始化克隆配合仓库在只有一个文件时可能比较快, 但是如果存储一个二进制文件, 特别是比较大的文件时, 可能在第一次请求配置时有延迟甚至可能导致服务端内存溢出.
2.1 Environment Repository
在 config server 中我们应该将配置存储在什么地方? 掌控这个行为的策略的就是为 Environment 对象服务的 EnvironmentRepository.
Environment 资源由一下三个变量参数化:
1){application} 对应客户端的 spring.application.name
2){profile} 对应客户端的 spring.profiles.active(以逗号分隔)
3){label} 它是服务器端功能标签 "版本化" 的配置文件集
Repository 的实现通常像一个 spring boot application, 从一个和 {application} 相等的 spring.config.name 参数和与 {profiles} 相等的 spring.profiles.active 参数指定的文件来加载配置.
优先级策略和普通 spring boot 的应用一样: Active profiles 优先级比默认的高, 如果有多个 profiles, 那么最后一个优先级最高. 下面是客户端 bootstrap 配置 bootstrap.yml:
- spring:
- application:
- name: foo
- profiles:
- active: dev,mysql
- (和一般 Spring Boot application 一样, 这些参数也可以在环境变量或者命令行参数中指定)
- 2.1.1 Git Backend
在 config server 中使用 spring.cloud.config.server.git.uri 来设置仓库位置, 如果 uri 是以 file: 开头, 则是本地仓库.
但是如果要扩展 config server 并且高可用的话, 必须使所有服务器实例指向同一个仓库. 因此需要一个共享的文件系统. 在这种情况下, 使用 ssh 协议是比较好的, 这样服务器可以克隆一份配置到本地作为缓存使用.
仓库的实现是将 HTTP 路径中的 {label} 映射到一个 git 标签 (commit id, branch name, or tag), 如果一个 git 分支或者标签中包含 "/" 斜杠, 那么在 HTTP url 中需要用一个特殊字符(_) 来替代, 以免发生混淆.
比如标签为 foo/bar, 则应该替换成: foo(_)bar. 这个规则同样可应用到 {application} 参数上.
- Skipping SSL Certificate Validation(跳过 ssl 验证)
- spring:
- cloud:
- config:
- server:
- git:
- uri: https://example.com/my/repo
- skipSslValidation: true
- Setting HTTP Connection Timeout(设置 HTTP 连接超时时间, 以秒为单位)
- spring:
- cloud:
- config:
- server:
- git:
- uri: https://example.com/my/repo
- timeout: 4
- Placeholders in Git URI(git URI 中的占位符)
Spring Cloud Config Server 支持 git URI 中的占位符为:{application},{profile},{label}(记住 label 是作为 git 的标签使用的). 通过下面的配置你可以支持每个应用一个仓库的策略:
- spring:
- cloud:
- config:
- server:
- git:
- uri: https://github.com/myorg/{application}
- Pattern Matching and Multiple Repositories(规则匹配和多仓库)
Spring Cloud Config 包含对 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" 仓库的规则是 simple/*({application}为 simple,{profile}为任意值)."local" 仓库匹配任何一个以 local 开头的应用名称, 如果没有指定 {profile} 规则, 则会自动在规则后面添加 "/*".
由于 pattern 参数实际上是一个数组, 所以使用 YAML 数组 (或者在. properties 文件中使用[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
每个仓库都可以在子目录中存储配置文件, 如果要在子目录中搜索则需要使用 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 的远程仓库会在启动时克隆, 其他的都是在第一次接受到配置请求时才克隆.
Authentication(用户验证)
添加 username 和 password 属性来使用远程仓库基于 HTTP 的验证. 例如:
- spring:
- cloud:
- config:
- server:
- git:
- uri: https://github.com/spring-cloud-samples/config-repo
- username: trolley
- password: strongpassword
如果不使用 HTTPS 和用户凭证, 也可以使用 SHH, 在默认目录下存储 key(~/.ssh), 并且 URI 指向一个 SSH 地址(例如: git@github.com:configuration/cloud-configuration).
Git SSH configuration using properties(使用属性配置 GIT SSH)
SSH 配置可以使用 java 属性来解决, spring.cloud.config.server.git.ignoreLocalSshSettings 值必须设置为 true. 例如:
- spring:
- cloud:
- config:
- server:
- git:
- uri: git@gitserver.com:team/repo1.git
- ignoreLocalSshSettings: true
- hostKey: someHostKey
- hostKeyAlgorithm: ssh-rsa
- privateKey: |
- -----BEGIN RSA PRIVATE KEY-----
- MIIEpgIBAAKCAQEAx4UbaDzY5xjW6hc9jwN0mX33XpTDVW9WqHp5AKaRbtAC3DqX
- IXFMPgw3K45jxRb93f8tv9vL3rD9CUG1Gv4FM+o7ds7FRES5RTjv2RT/JVNJCoqF
- ol8+ngLqRZCyBtQN7zYByWMRirPGoDUqdPYrj2yq+ObBBNhg5N+hOwKjjpzdj2Ud
- 1l7R+wxIqmJo1IYyy16xS8WsjyQuyC0lL456qkd5BDZ0Ag8j2X9H9D5220Ln7s9i
- oezTipXipS7p7Jekf3Ywx6abJwOmB0rX79dV4qiNcGgzATnG1PkXxqt76VhcGa0W
- DDVHEEYGbSQ6hIGSh0I7BQun0aLRZojfE3gqHQIDAQABAoIBAQCZmGrk8BK6tXCd
- fY6yTiKxFzwb38IQP0ojIUWNrq0+9Xt+NsypviLHkXfXXCKKU4zUHeIGVRq5MN9b
- BO56/RrcQHHOoJdUWuOV2qMqJvPUtC0CpGkD+valhfD75MxoXU7s3FK7yjxy3rsG
- EmfA6tHV8/4a5umo5TqSd2YTm5B19AhRqiuUVI1wTB41DjULUGiMYrnYrhzQlVvj
- 5MjnKTlYu3V8PoYDfv1GmxPPh6vlpafXEeEYN8VB97e5x3DGHjZ5UrurAmTLTdO8
- +AahyoKsIY612TkkQthJlt7FJAwnCGMgY6podzzvzICLFmmTXYiZ/28I4BX/mOSe
- pZVnfRixAoGBAO6Uiwt40/PKs53mCEWngslSCsh9oGAaLTf/XdvMns5VmuyyAyKG
- ti8Ol5wqBMi4GIUzjbgUvSUt+IowIrG3f5tN85wpjQ1UGVcpTnl5Qo9xaS1PFScQ
- xrtWZ9eNj2TsIAMp/svJsyGG3OibxfnuAIpSXNQiJPwRlW3irzpGgVx/AoGBANYW
- dnhshUcEHMJi3aXwR12OTDnaLoanVGLwLnkqLSYUZA7ZegpKq90UAuBdcEfgdpyi
- PhKpeaeIiAaNnFo8m9aoTKr+7I6/uMTlwrVnfrsVTZv3orxjwQV20YIBCVRKD1uX
- VhE0ozPZxwwKSPAFocpyWpGHGreGF1AIYBE9UBtjAoGBAI8bfPgJpyFyMiGBjO6z
- FwlJc/xlFqDusrcHL7abW5qq0L4v3R+FrJw3ZYufzLTVcKfdj6GelwJJO+8wBm+R
- gTKYJItEhT48duLIfTDyIpHGVm9+I1MGhh5zKuCqIhxIYr9jHloBB7kRm0rPvYY4
- VAykcNgyDvtAVODP+4m6JvhjAoGBALbtTqErKN47V0+JJpapLnF0KxGrqeGIjIRV
- cYA6V4WYGr7NeIfesecfOC356PyhgPfpcVyEztwlvwTKb3RzIT1TZN8fH4YBr6Ee
- KTbTjefRFhVUjQqnucAvfGi29f+9oE3Ei9f7wA+H35ocF6JvTYUsHNMIO/3gZ38N
- CPjyCMa9AoGBAMhsITNe3QcbsXAbdUR00dDsIFVROzyFJ2m40i4KCRM35bC/BIBs
- q0TY3we+ERB40U8Z2BvU61QuwaunJ2+uGadHo58VSVdggqAo0BSkH58innKKt96J
- 69pcVH/4rmLbXdcmNYGm6iu+MlPQk4BUZknHSmVHIFdJ0EPupVaQ8RHT
- -----END RSA PRIVATE KEY-----
其中 hostKeyAlgorithm 必须是 ssh-dss, ssh-rsa, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, or ecdsa-sha2-nistp521 中的一个.
Force pull in Git Repositories
如果本地 copy 已经失效(即远程仓库有改动), 则 Spring Cloud Config Server 会强制从从远程库拉取最新的配置. 如下:
- spring:
- cloud:
- config:
- server:
- git:
- uri: https://github.com/spring-cloud-samples/config-repo
- force-pull: true
如果有多个远程仓库的话, 可以使用类似下面的配置:
- 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.
Deleting untracked branches in Git Repositories(删除 git 仓库中未跟踪的分支)
因为 Spring Cloud Config Server 会克隆远程仓库到本地并且会一直保持这个分支知道下次重启, 所以有一种情况是远程分支已经被删除, 但是本地副本还仍然可用.
为了保证本地仓库分支和远程同步, 需要设置 deleteUntrackedBranches 属性, 它会使 Spring Cloud Config Server 强制删除本地未跟踪的分支. 例如:
- spring:
- cloud:
- config:
- server:
- git:
- uri: https://github.com/spring-cloud-samples/config-repo
- deleteUntrackedBranches: true
deleteUntrackedBranches 默认值为 false.
- 3. Spring Cloud Config Client(配置客户端)
- 3.1 Config First Bootstrap(启动时先读取 config server 配合)
在 classpath 中存在 Spring Cloud Config Client 的任何应用的默认行为如下: 当一个 config 客户端启动时, 它绑定到 Config Server(通过 bootstrap 的配置属性 spring.cloud.config.uri)然后使用远程配置文件初始化 spring 环境.
这种行为的最终结果是所有想要到 Config Server 消费的客户端应用都需要一个配置有 spring.cloud.config.uri(默认为:"http://localhost:8888")的 bootstrap.yml 或者环境变量.
3.2 Discovery First Bootstrap(使用服务发现寻找 config server)
如果你正在使用服务发现框架例如 Spring Cloud Netflix 和 Eureka Service Discovery 或者 Spring Cloud Consul, 你可以把 Config Server 注册到服务注册中心.
但是在默认的 "Config First" 模式下, 客户端是感知不到注册中心中的 config server 服务的. 如果你选择使用服务发现来定位 Config Server, 那么你需要在 Config server 中设置 spring.cloud.config.discovery.enabled=true,
默认是 false. 这么做的话就需要每个客户端应用都要有一个 bootstrap.yml 或者环境变量来配置服务注册中心的内容. 例如在 Spring Cloud Netflix 中, 你需要配置 Eureka server 地址(eureka.client.serviceUrl.defaultZone),
这么做的代价是在启动时需要一个额外的网络往返来定位服务注册中心. 好处是, 只要注册中心是固定的, 那么 config server 就可以随意改变坐标. 默认的服务 ID 是 configserver, 但是可以通过 spring.cloud.config.discovery.serviceId
来重新设置(但是通常是通过 spring.application.name 来设置一个服务 ID).
一般服务发现实现客户端都是支持某些元数据映射的(例如在 Eureka 中的 eureka.instance.metadataMap). 为了让配置客户端能正确连接到 config server 需要在 Config Server 中配一些服务注册相关的元数据.
如果 Config Server 安全策略是基于 HTTP 的, 你可以设置一些用户凭证像 username,password. 另外, 如果 Config Server 有上下文路径, 可以使用 configPath 设置. 如下(bootstrap.yml):
- eureka:
- instance:
- ...
- metadataMap:
- user: osufhalskjrtl
- password: lviuhlszvaorhvlo5847
- configPath: /config
- 3.3 Config Client Fail Fast(快速失败响应)
在某些情况下, 你可能希望服务在启动时如果连接 config server 失败时立刻响应失败而停止启动, 可以设置 spring.cloud.config.fail-fast=true.
3.4 Config Client Retry(配置客户端重试机制)
如果你觉得 config server 在你启动应用是不可达是暂时的或者偶然的, 你需要在一次失败后接着重新尝试连接. 第一步, 设置 spring.cloud.config.fail-fast=false.
接着将 spring-retry 和 spring-boot-starter-aop 加入到 classpath 中. 默认行为是重试 6 次, 初始间隔为 1000ms, 后续间隔乘以 1.1.
可以通过设置 spring.cloud.config.retry.* 来改变默认行为.
注意: 如果要完全控制重试机制, 可以通过创建一个 RetryOperationsInterceptor 类型 id 为 configServerRetryInterceptor 的 bean.
可以使用 Spring Retry 中的 RetryInterceptorBuilder 来创建.
3.5 Locating Remote Configuration Resources(定位远程配置资源)
配置服务提供 /{name}/{profile}/{label}的属性源, 其在客户端应用的映射为:
- "name" =
- ${spring.application.name}
- "profile" =
- ${spring.profiles.active}(其实是 Environment.getActiveProfiles())
- "label" = "master"
可以使用 spring.cloud.config.* 来覆盖上面的默认值.
其中可以使用 label 属性回滚到以前的版本. 在 config server 的实现中, label 可以是 git 标签, 分支名或者 commit ID. 也可以是以逗号分隔的列表. 在这种列表情况下, 其中的元素会一个一个的被尝试, 直到有一个成功.
3.6 Specifying Multiple Urls for the Config Server(指定多个 config server url)
为了保证高可用, 你可能部署多个 config server, 在客户端可以使用 spring.cloud.config.uri, 以逗号分隔指定多个 URL, 或者将 config server 的多个实例注册到服务注册中心, 此时客户端需要使用之前提到的 Discovery-First Bootstrap
模式(spring.cloud.config.discovery.enabled=true).
如果 Config Server 使用的是 HTTPS 协议, 则可以将用户凭证信息填写在每个 config server 的 url 上. 如果使用其他的安全机制, 则不支持为每个 config server 配置验证信息.
3.7 Configuring Read Timeouts(读取超时)
使用 spring.cloud.config.request-read-timeout 配置超时时间.
3.8 Security(安全机制)
如果 config server 使用的是 HTTPS, 则需要在 url 上指定用户名和密码, 或者使用单独的 username 和 password 属性设置. 如下(bootstrap.yml)
- spring:
- cloud:
- config:
- uri: https://user:secret@myconfig.mycompany.com
- spring:
- cloud:
- config:
- uri: https://myconfig.mycompany.com
- username: user
- password: secret
spring.cloud.config.password 和 spring.cloud.config.username 会覆盖 url 中的用户名和密码.
好了, spring cloud config 就先讲到这. 下一篇就是 spring cloud netflix. 如果文章中写的有问题的希望各位读者批评指出. 如果觉得在我这学到了点东西的, 特别希望您能动动可爱的小手给点个赞!^_^
来源: https://www.cnblogs.com/CLAYJJ/p/9633109.html