本文导读:
Spring Cloud Config 基本概念
Spring Cloud Config 客户端加载流程
Spring Cloud Config 基于消息总线配置
Spring Cloud Config 中的占位符
Spring Cloud Config 仓库最佳实践
Spring Cloud Config 健康检查问题剖析
本文主要介绍 Spring Cloud Config 基本概念、实践过的配置及遇到的问题进行剖析。关于如何启动运行配置中心可以参考官方 Demo。
本文基于 Spring Cloud Edgware.SR3 版本实践。
Spring Cloud Config 基本概念Spring Cloud Config 用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持。
服务端:分布式配置中心,独立的微服务应用,用来连接配置仓库(GIT)并为客户端提供获取配置信息、加密/解密等访问接口。
客户端:微服务架构中各个微服务应用和基础设施,通过指定配置中心管理应用资源与业务相关的配置内容,启动时从配置中心获取和加载配置信息
SCC作用:
实现了对服务端和客户端中环境变量和属性配置的抽象映射。
SCC优势:
默认采用 GIT 存储配置信息,天然支持对配置信息的版本管理。
Spring Cloud Config架构图:
如上图所示,架构图中的几个主要元素作用: 远程 GIT 仓库:
用来存储配置文件的地方。
Config Server:
分布式配置中心,微服务中指定了连接仓库的位置以及账号密码等信息。
本地 GIT 仓库:
在 Config Server 文件系统中,客户单每次请求获取配置信息时,Config Server 从 GIT 仓库获取最新配置到本地,然后在本地 GIT 仓库读取并返回。当远程仓库无法获取时,直接将本地仓库内容返回。
ServerA/B:
具体的微服务应用,他们指定了 Config Server 地址,从而实现外部化获取应用自己想要的配置信息。应用启动时会向 Config Server 发起请求获取配置信息进行加载。
消息中心:
上述第二个架构图是基于消息总线的方式,依赖的外部的 MQ 组件,目前支持 Kafka、Rabbitmq。通过 Config Server 配置中心提供的 /bus/refresh endpoint 作为生产者发送消息,客户端接受到消息通过http接口形式从 Config Server 拉取配置。
服务注册中心:
Spring Cloud Config 客户端加载流程可以将 Config Server 注册到服务注册中心上比如 Eureka,然后客户端通过服务注册中心发现Config Server 服务列表,选择其中一台 Config Server 来完成健康检查以及获取远端配置信息。
客户端应用从配置管理中获取配置执行流程:
1)应用启动时,根据 bootstrap.yml 中配置的应用名 {application}、环境名 {profile}、分支名 {label},向 Config Server 请求获取配置信息。
2)Config Server 根据自己维护的 GIT 仓库信息与客户端传过来的配置定位去查找配置信息。
3)通过 git clone 命令将找到的配置下载到 Config Server 的文件系统(本地GIT仓库)
4)Config Server 创建 Spring 的 ApplicationContext 实例,并从 GIT 本地仓库中加载配置文件,最后读取这些配置内容返回给客户端应用。
5)客户端应用在获取外部配置内容后加载到客户端的 ApplicationContext 实例,该配置内容优先级高于客户端 Jar 包内部的配置内容,所以在 Jar 包中重复的内容将不再被加载。
Spring Cloud Config 基于消息总线配置Config Server 作为配置中心 pom.xml 引入:
<dependency>
Config Server 配置文件(yml格式):
server:
Config Client 作为客户端 pom.xml 引入:
<dependency>
Config Client 配置文件(yml格式):
spring:
Spring Cloud Config 中的占位符
占位符的使用:
这里的 {application} 代表了应用名,当客户端向 Config Server 发起获取配置请求时,Config Server 会根据客户端的 spring.application.name 信息来填充 {application} 占位符以定位配置资源的存储位置。
注意:{label} 参数很特别,如果 GIT 分支和标签包含 “/”,那么 {label} 参数在 HTTP 的 URL 中应用使用 “(_)” 替代,以避免改变了 URI 含义,指向到其他 URI 资源。
为什么要有占位符?
Spring Cloud Config 仓库最佳实践当使用 GIT 作为配置中心来存储各个微服务应用的配置文件时,URI 中的占位符的使用可以帮助我们规划和实现通用的仓库配置。
本地仓库:
Spring Cloud 的 D、E 版本中默认存储到 /var/folders/ml/9rww8x69519fwqlwlt5jrx700000gq/T/config-repo-2486127823875015066目录下。
在 B 版本中,未实际测试过,存储到临时目录 /tmp/config-repo-随机数目录下。 为了避免一些不可预知的问题,我们设置一个固定的本地GIT仓库目录。
spring.cloud.config.server.git.basedir=${user.home}/local-config-repo
这个配置中,如果${user.home} 目录下发现 local-config-repo 不存在,在 Config Server 启动后会自动创建,并从 GIT 远程仓库下载配置存储到这个位置。
远程仓库实践:
单仓库目录:每一个项目对应一个仓库 spring.cloud.config.server.git.uri=https://gitee.com/ldwds/{application}
多仓库目录:同一个仓库下,每个项目一个目录 spring.cloud.config.server.git.uri=https://gitee.com/ldwds/config-repo-demo.git
spring.cloud.config.server.git.search-paths='{application}'
1)单仓库目录注意事项:
spring.cloud.config.server.git.uri=[https://gitee.com/ldwds/config-repo-demo/](https://gitee.com/ldwds/config-repo-demo/)
客户端应用启动前,在 config-repo-demo 仓库下创建子目录,子目录名称就是配置中指定的spring.application.name 应用名。
否则,工程中引用的属性找不到,会报如下错误: Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'from' in value "${from}"
2)多仓库目录注意事项:
这种方式不能设置参数 spring.cloud.config.server.git.force-pull=true
和 spring.cloud.config.server.git.clone-on-start=true
否则启动会报错,也很好理解因为使用了 {applicatoin} 作为占位符,没有指明具体的仓库名,所以无法强制拉取远程仓库配置。
如果你设置了本地仓库目录比如 spring.cloud.config.server.git.basedir=/data/config-repos/local-config-repo
Config Server 启动后会自动创建 /data/config-repos 目录,并创建 config-repo-随机数命名的仓库名录,这个仓库下的内容来自于健康检查的默认仓库app。
客户端应用启动后,会根据 {application} 应用名去查找该仓库,Config Server 从匹配 Git 仓库并 clone 到 config-repo-随机数的目录下。
如果 Config Server 重启了,客户端应用通过 /bus/refresh 刷新配置,因为并没有缓存之前的仓库名,所以会自动创建一个 config-repo-随机数 的仓库目录并从 Git clone 数据。
如果 Config Server 已有本地仓库,客户端重启或/bus/refresh刷新配置则 Config Server 不会重建新的仓库。
配置中心本地仓库执行原理:
本地仓库是否存在根据 basedir 目录下是否包含.git 隐藏文件。
如果本地仓库不存在,则从远端仓库 clone 数据到本地;如果本地仓库存在,则从远程仓库 fetch 最新数据到本地。
然后 checkout 到指定 label,从远端仓库 merge 数据,并获取当前 label 分支最新的HEAD 版本,以及默认的应用名 app 作为环境信息返回。
Spring Cloud Config健康检查问题剖析健康检查 pom.xml 中引入:
<dependency>
添加上述依赖后,默认开启健康检查。如果不需要健康检查,可以通过 spring.cloud.config.server.health.enabled=false
参数设定关闭。
如果配置为: spring.cloud.config.server.git.uri=[https://gitee.com/ldwds/config-repo-demo.git](https://gitee.com/ldwds/config-repo-demo.git)
默认开启了健康检查,我开始认为默认检查应用名称为 app,profiles 为 default,label 为 null进行监控(源码中看到的)。
但是 GIT 配置仓库下并没有 app 应用,此时访问 /health,监控状态仍然是 UP?
{
上述理解是错误的,原因分析如下:
这个主要跟配置中心指定的 GIT 仓库地址有关系。
如果仓库地址指定的是 https://gitee.com/ldwds/{application} ,检查监视器会将 {application} 替换为默认应用名 app 作为仓库地址,此时会在 {user.home} 目录下创建 config-repo-随机数作为 {application} 应用的本地仓库(如:/Users/liudewei1228/config-repo-7949870192520306956)。
即使设置了
spring.config.server.git.basedir=${user.home}/local-config-repo/
也不会被使用到。 为什么?因为 {application} 作为仓库,是个动态的,可能会有多个 {application} 项目仓库,所以不会使用 basedir 特定目录作为本地仓库。
如下参数设置健康检查的配置:
spring.cloud.config.server.health.repositories.config-repo-demo.name=应用名
找到环境信息即显示状态 UP,此过程出现任何异常(如找不到仓库 NoSuchRespositoryException)就会显示 DOWN 状态。
在uri中包含 {application} 作为仓库情况下,客户端应用在启用前需提前创建好spring.application.name=config-client应用名作为仓库,否则会导致无法启用。(因为 {application} 被认为是一个项目仓库,并不是一个目录)。
源码详见:ConfigServerHealthIndicator.java 的 doHealthCheck 方法。
配置正确仓库的 name、label、profiles,访问 /health 接口显示 sources,这个 sources 中的地址无法访问的,实际只是一个标识的作用。
访问/health结果:
{
否则,找不到指定仓库的信息,只会显示如下信息:
{
最新 Spring Cloud Config 改进了很多问题,大家可以结合官网进一步学习了解。
本文对 Spring Cloud Config (Spring Cloud E 版本)的基本概念、基于消息总线的配置使用、仓库目录实践、健康检查的实践以及实践中遇到的问题进行了剖析,希望有使用到这个配置中心的朋友们有所帮助。
目前微服务架构中选型时,推荐使用国内开源的配置中心:Apollo配置中心(携程开源)、Nacos注册&配置中心(阿里巴巴开源)。
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️