Spring Cloud Config 远程配置获取流程:客户端与服务端交互详解
Spring Cloud Config 的核心能力是实现配置的远程管理与分发,其底层通过客户端主动拉取和服务端按需提供的方式完成配置交互。本文从客户端和服务端两方面,结合源码解析远程配置的获取全流程。
客户端(Config Client)获取远程配置的流程
客户端获取远程配置的核心是 PropertySourceLocator 接口,其实现类 ConfigServicePropertySourceLocator 负责与服务端通信并拉取配置。
核心接口:PropertySourceLocator
PropertySourceLocator 是 Spring Cloud 定义的配置源定位接口,用于从远程(如 Config Server)或本地加载配置,核心方法为 locate:
1 | public interface PropertySourceLocator { |
Spring Cloud Config 客户端通过 ConfigServicePropertySourceLocator 实现该接口,完成远程配置拉取。
客户端拉取配置的触发时机
客户端配置拉取发生在 Spring Boot 启动的早期阶段( Bootstrap 阶段),由以下组件协同触发:
(1)Bootstrap 上下文初始化
Spring Cloud 会创建一个独立的 Bootstrap Context( Bootstrap 上下文),作为应用主上下文的父上下文,专门用于加载远程配置。其初始化由 BootstrapApplicationListener 监听器触发:
1 | // SpringApplication 构造器中注册监听器 |
BootstrapApplicationListener 是关键监听器,会在应用启动时触发 Bootstrap 上下文的初始化。
(2)PropertySourceBootstrapConfiguration 执行配置加载
在 Bootstrap 上下文初始化过程中,PropertySourceBootstrapConfiguration(ApplicationContextInitializer 的实现类)会被执行。其 initialize 方法遍历所有 PropertySourceLocator 实例,调用 locate 方法拉取配置:
1 |
|
ConfigServicePropertySourceLocator 拉取配置的细节
ConfigServicePropertySourceLocator 的 locate 方法是客户端拉取配置的核心实现,步骤如下:
(1)构建请求参数
从客户端环境中提取配置参数(应用名、环境、分支等):
1 | ConfigClientProperties properties = this.defaultProperties.override(environment); |
(2)通过 RestTemplate 调用 Config Server
客户端通过 RestTemplate 向 Config Server 发送 HTTP 请求,路径格式为 /{name}/{profile}/{label}:
1 | // 调用远程配置中心 |
getRemoteEnvironment 方法内部构造请求 URL(如 http://config-server:7010/user-service/dev/master),并发送 GET 请求。
(3)处理服务端响应
服务端返回 Environment 对象(包含配置键值对),客户端将其转换为 PropertySource 并添加到本地环境中:
1 | for (PropertySource source : result.getPropertySources()) { |
至此,客户端成功获取远程配置,后续应用启动时可直接读取这些配置。
服务端(Config Server)提供远程配置的流程
服务端接收客户端的配置请求后,从 Git 等存储源加载配置并返回,核心由 EnvironmentController 和 EnvironmentRepository 协同完成。
接收客户端请求:EnvironmentController
Config Server 通过 EnvironmentController 暴露 REST 接口,接收客户端的配置请求:
1 |
|
加载配置:EnvironmentRepository
EnvironmentRepository 是服务端加载配置的核心接口,Git 存储对应实现类 JGitEnvironmentRepository(或 MultipleJGitEnvironmentRepository 用于多仓库场景)。
(1)多仓库场景:MultipleJGitEnvironmentRepository
若配置了多个 Git 仓库,MultipleJGitEnvironmentRepository 会先匹配当前请求对应的仓库:
1 | public Environment findOne(String application, String profile, String label, boolean includeOrigin) { |
(2)单仓库场景:JGitEnvironmentRepository
对于匹配的仓库,JGitEnvironmentRepository 完成配置加载,步骤如下:
① 克隆 / 拉取 Git 仓库到本地
服务端首次启动(或配置 clone-on-start: true)时,将远程 Git 仓库克隆到本地缓存目录;后续请求会先拉取最新代码(force-pull: true 配置强制拉取):
1 | // 克隆远程仓库到本地 |
② 从本地仓库加载配置文件
仓库准备完成后,服务端通过 NativeEnvironmentRepository 从本地缓存目录加载配置文件(如 user-service-dev.yml):
1 | public Environment findOne(String application, String profile, String label, boolean includeOrigin) { |
③ 转换为 Environment 对象
本地配置文件被加载后,转换为 Environment 对象(包含配置源、版本、分支等信息),返回给客户端:
1 | // Environment 包含多个 PropertySource(对应多个配置文件) |
客户端与服务端交互的完整流程总结
- 客户端启动:触发 Bootstrap 上下文初始化,
PropertySourceBootstrapConfiguration调用ConfigServicePropertySourceLocator的locate方法。 - 客户端请求:通过 RestTemplate 向 Config Server 发送请求(
/{name}/{profiles}/{label})。 - 服务端接收请求:
EnvironmentController接收请求,调用EnvironmentRepository加载配置。 - 服务端加载配置:
JGitEnvironmentRepository从 Git 仓库(本地缓存)加载配置文件,转换为Environment对象。 - 服务端响应:将
Environment对象返回给客户端。 - 客户端处理响应:将
Environment转换为PropertySource,添加到本地环境中,供应用启动使用