原创 吴就业 128 0 2020-07-05
本文为博主原创文章,未经博主允许不得转载。
本文链接:https://wujiuye.com/article/c199f9c21a824710942b24db2802911b
作者:吴就业
链接:https://wujiuye.com/article/c199f9c21a824710942b24db2802911b
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。
本篇文章写于2020年07月05日,从公众号|掘金|CSDN手工同步过来(博客搬家),本篇为原创文章。
Spring
为Spring Cloud
在Bean
的生命周期、Bean
的BeanPostProcessor
以及AOP
层面提供实现动态刷新配置的支持,而Spring Cloud
则是为使用者提供实现动态加载配置的接口层面支持,封装了复杂的实现逻辑,让第三方配置中心实现整合到Spring Cloud
项目提供方便。
Spring Cloud Kubernetes
也为我们使用原生服务实现动态配置提供支持,它帮我们实现Spring Cloud
的动态配置接口,我们只需要在bootstarp.yaml
添加简单的配置就能使用Kubernetes
的原生服务做为配置中心并实现动态加载配置。动态配置做为Kubernetes
的ConfigMap
资源存储在etcd
服务。
本篇我们继续通过了解Spring Cloud Kubernetes
实现动态加载配置接口来理解Spring Cloud
动态配置实现的整个流程。
本篇内容:
* Spring Cloud Kubernetes
动态配置使用方式
* Spring Cloud Kubernetes
动态配置实现原理
* 从Spring Cloud Kubernetes Config
源码分析实现原理
关于如何使用动态配置以及监听配置改变,笔者在《Spring Cloud kubernetes
入门项目sck-demo
》这篇文章已经介绍了详细的使用步骤,本篇再对整个使用流程做个总结,概括使用步骤。
Properties
类例如,编写用于装载数据库配置的DataBaseProperties
类,在Properties
类上添加@RefreshScope
、@ConfigurationProperties
、@Component
这三个注解。
pom.xml
文件中添加spring-cloud-kubernetes-config
依赖<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-config</artifactId>
</dependency>
bootstrap.yaml
文件中添加启用kubernetes
动态配置功能的配置由于Spring Cloud
只提供动态拉取配置的接口,并不能提供动态拉取配置的实现,这只能由配置中心在Client
端实现。因此,在使用kubernetes
原生服务做为配置中心时,需要指定项目中引用的哪些ConfigMap
资源,只有这样Spring Cloud Kubernetes Config
才知道读取哪些ConfigMap
资源下的动态配置数据。
在bootstrap.yaml
配置引用的ConfigMap
资源。
spring:
cloud:
kubernetes:
reload:
enabled: true
config:
## 数组,引用的多个ConfigMap资源名称
sources:
- name: [ConfigMap资源名称]
reload.enabled
:配置开启配置的reload
功能,默认是flase
;config
:配置引用的ConfigMap
资源名称,这是个数组,可以配置引用多个资源的名称。比如我们可以将数据库的配置、Redis
缓存的连接配置、消息中间件的配置等分到不同的ConfigMap
资源存储,这样的好处当然是减少单个配置文件的配置信息。因为yaml
是严格的空格党,如果配置文件写的配置信息很多,一不小心少了一个缩进,就可能把数据库的配置添加到了Redis
的配置上,这将会导致应用程序瘫痪,直到你把问题找出来并解决。
kubernetes
控制台添加ConfigMap
资源,在ConfigMap
资源描述文件中添加配置你可以使用API
方式或者kubectl
去增删改一个ConfigMap
资源,也可以在控制台去操作,这取决于你的喜好。
如果有需要,你可以选择监听RefreshScopeRefreshedEvent
事件或EnvironmentChangeEvent
事件,当接收到事件时,去实现一些操作。
例如,当数据库连接配置修改,在监听到RefreshScopeRefreshedEvent
事件后,去重新创建数据库连接池,当然,我们一般不会去做这个事情,这与重启应用没有多大的差别。
与服务注册和发现一样,Spring Cloud Kubernetes
实现动态刷新配置也是通过定时或监听事件的方式调用Kubernetes API
获取
ConfigMap
资源存储的用户配置数据。ConfigMap
资源描述文件中的data
项用于存储用户的配置数据。
在获取到配置数据后,先将新获取的配置数据与当前正在使用的配置数据做比较,如果配置有变化就调用Spring Cloud
的API
刷新配置,即调用ContextRefresher
对象的refresh
方法。
Spring Cloud
在刷新配置之前会发送一个EnvironmentChangeEvent
事件,在刷新配置之后,会发送一个RefreshScopeRefreshedEvent
事件。
在前面分析Spring Cloud
实现动态配置的源码时,我们还漏考虑了一个问题。如果使用动态配置,那么,在应用程序启动时,应用容器(ApplicationContext
)启动之前,肯定是需要能够从配置中心拉取一次配置,否则应用将启动不起来。
上一篇文章分析Spring Cloud
应用的启动流程也是为本篇作铺垫的。Spring Cloud
应用启动流程:
PropertySourceLocator
是Spring Cloud
提供的一个接口,用于动态从配置中心拉取配置。
public interface PropertySourceLocator {
/**
* @param environment The current Environment.
* @return A PropertySource, or null if there is none.
* @throws IllegalStateException if there is a fail-fast condition.
*/
PropertySource<?> locate(Environment environment);
}
实现PropertySourceLocator
接口需要实现locate
方法,即从配置中心拉取配置。
动态配置的初始化流程:
Spring Cloud
的Bootstrap
容器中注册PropertySourceLocator
;prepareContext
)阶段会发送一个ConfigurableApplicationContext
事件,Spring Cloud
监听ConfigurableApplicationContext
事件,并在initialize
方法中通过PropertySourceLocator
从配置中心拉取配置;prepareContext
阶段结束后,此时环境Environment
中已经存在启动应用容器所需的配置了,往下refreshContext
阶段就能正常启动应用容器;PropertySourceLocator
是注册到Bootstrap
容器的,但可通过父工厂拿到PropertySourceLocator
。如果PropertySourceLocator
拉取配置失败,那么后续refresh
应用容器将会失败,程序异常退出。
Spring Cloud Kubernetes
实现动态配置的源码在spring-cloud-kubernetes-config
模块。该模块也是一个starter
包,在META-INF
目录有个spring.factories
文件。该文件中配置注册到应用容器的自动配置类ConfigReloadAutoConfiguration
、以及注册到Spring Cloud
的Bootstrap
容器中的配置类BootstrapConfiguration
。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.kubernetes.config.reload.ConfigReloadAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.kubernetes.config.BootstrapConfiguration
通过上一篇的学习我们知道,spring.factories
中注册的BootstrapConfiguration
是注册到Bootstrap
容器的,也就是Spring Boot
启动的应用容器的父容器。Spring Cloud
的Bootstrap
容器为Spring Boot
启动应用容器提供前置条件,例如环境准备,完成Spring Boot
启动应用容器所需要的条件。
BootstrapConfiguration
中注册的Bean
有:与Kubernetes
交互的KubernetesClient
、用于动态加载配置的ConfigMapPropertySourceLocator
。用于确保在Spring Boot
启动应用容器时能够从配置中心拉取到配置。
KubernetesClient
在Spring Cloud Kubernetes
项目中的地位很高,也是最需要优先被创建的,因为它提供访问Kubernetes API
的能力,只有通过它才能调用Kubernetes API
实现服务发现、加载动态配置。这与web
应用需要先启动tomcat
才能接收到请求一样。
ConfigReloadAutoConfiguration
中注册的Bean
有:ConfigurationChangeDetector
、ConfigurationUpdateStrategy
。
这两个Bean
都是spring-cloud-kubernetes-config
模块为实现动态拉取配置提供的,并非是实现Spring Cloud
的接口。spring-cloud-kubernetes-config
模块只是实现Spring Cloud
的PropertySourceLocator
接口。
ConfigurationUpdateStrategy
:动态配置的更新策略,支持RESTART_CONTEXT
、REFRESH
、SHUTDOWN
。
默认使用REFRESH
策略,即调用Spring Cloud
提供的ContextRefresher
的refresh
方法刷新环境,刷新带有@ConfigurationProperties
或@RefreshScope
注释的bean
。RESTART_CONTEXT
策略为重启,SHUTDOWN
策略为停止应用进程。
可在bootstrap.yaml
配置文件中配置使用的动态配置更新策略。
spring:
cloud:
kubernetes:
reload:
strategy: REFRESH
ConfigurationChangeDetector
:动态配置改变探测器。用于实现动态感知配置的改变,只在探测到有配置信息改变时,才会调用更新策略(ConfigurationUpdateStrategy
)更新配置。
Spring Cloud Kubernetes Config
为我们提供两种动态感知配置改变的探测器,一种是定时轮询探测器(POLLING
),另一种是基于事件监听的探测器(EVENT
),后者类似于ZK
的监听机制。默认使用的是EVENT
。
如果想使用定时轮询策略,可在bootstrap.yaml
配置文件中添加如下配置。
spring:
cloud:
kubernetes:
reload:
mode: polling
period: 5000
即使用定时轮询探测器,每5
秒从配置中心拉取一次配置,也就是读取一次ConfigMap
资源。被引用的每个ConfigMap
资源都会被读取一次,所以叫轮询。
Spring Cloud Kubernetes
动态配置的实现原理难点不在Spring Cloud Kubernetes Config
模块是如何实现的,而在于理解Spring Cloud
的动态配置刷新机制,以及Spring Cloud
应用的启动流程、被@RefreshScope
注解注释的Bean
的动态代理的实现。
声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。
本篇分析Spring Cloud Kubernetes服务注册与发现实现原理,以及Spring Cloud Kubernetes Core&Discovery源码分析。
订阅
订阅新文章发布通知吧,不错过精彩内容!
输入邮箱,提交后我们会给您发送一封邮件,您需点击邮件中的链接完成订阅设置。