前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Cloud Kubernetes动态配置实现原理与源码分析

Spring Cloud Kubernetes动态配置实现原理与源码分析

作者头像
吴就业
发布2020-07-10 11:39:11
1.1K0
发布2020-07-10 11:39:11
举报
文章被收录于专栏:Java艺术Java艺术

SpringSpring CloudBean的生命周期、BeanBeanPostProcessor以及AOP层面提供实现动态刷新配置的支持,而Spring Cloud则是为使用者提供实现动态加载配置的接口层面支持,封装了复杂的实现逻辑,让第三方配置中心实现整合到Spring Cloud项目提供方便。

Spring Cloud Kubernetes也为我们使用原生服务实现动态配置提供支持,它帮我们实现Spring Cloud的动态配置接口,我们只需要在bootstarp.yaml添加简单的配置就能使用Kubernetes的原生服务做为配置中心并实现动态加载配置。动态配置做为KubernetesConfigMap资源存储在etcd服务。

本篇我们继续通过了解Spring Cloud Kubernetes实现动态加载配置接口来理解Spring Cloud动态配置实现的整个流程。

本篇内容:

  • Spring Cloud Kubernetes动态配置使用方式
  • Spring Cloud Kubernetes动态配置实现原理
  • Spring Cloud Kubernetes Config源码分析

Spring Cloud Kubernetes动态配置的使用方式

  • 1、与装载静态配置一样,编写用于装载动态配置的Properties

例如,编写用于装载数据库配置的DataBaseProperties类,在Properties类上添加@RefreshScope@ConfigurationProperties@Component这三个注解。

  • 2、pom.xml文件中添加spring-cloud-kubernetes-config依赖
代码语言:javascript
复制
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
</dependency>
  • 3、bootstrap.yaml文件中添加启用kubernetes动态配置功能的配置

由于Spring Cloud只提供动态拉取配置的接口,并不能提供动态拉取配置的实现,这只能由配置中心在Client端实现。因此,在使用kubernetes原生服务做为配置中心时,需要指定项目中引用的哪些ConfigMap资源,只有这样Spring Cloud Kubernetes Config才知道读取哪些ConfigMap资源下的动态配置数据。

bootstrap.yaml配置引用的ConfigMap资源。

代码语言:javascript
复制
spring:
  cloud:
    kubernetes:
      reload:
        enabled: true
      config:
        ## 数组,引用的多个ConfigMap资源名称
        sources:
          - name: [ConfigMap资源名称]
  • reload.enabled:配置开启配置的reload功能,默认是flase
  • config:配置引用的ConfigMap资源名称,这是个数组,可以配置引用多个资源的名称。

比如我们可以将数据库的配置、Redis缓存的连接配置、消息中间件的配置等分到不同的ConfigMap资源存储,这样的好处当然是减少单个配置文件的配置信息。因为yaml是严格的空格党,如果配置文件写的配置信息很多,一不小心少了一个缩进,就可能把数据库的配置添加到了Redis的配置上,这将会导致应用程序瘫痪,直到你把问题找出来并解决。

  • 4、kubernetes控制台添加ConfigMap资源,在ConfigMap资源描述文件中添加配置

你可以使用API方式或者kubectl去增删改一个ConfigMap资源,也可以在控制台去操作,这取决于你的喜好。

  • 5、监听配置改变事件

如果有需要,你可以选择监听RefreshScopeRefreshedEvent事件或EnvironmentChangeEvent事件,当接收到事件时,去实现一些操作。

例如,当数据库连接配置修改,在监听到RefreshScopeRefreshedEvent事件后,去重新创建数据库连接池,当然,我们一般不会去做这个事情,这与重启应用没有多大的差别。

Spring Cloud Kubernetes动态配置的实现原理

与服务注册和发现一样,Spring Cloud Kubernetes实现动态刷新配置也是通过定时或监听事件的方式调用Kubernetes API获取 ConfigMap资源存储的用户配置数据。ConfigMap资源描述文件中的data项用于存储用户的配置数据。

在获取到配置数据后,先将新获取的配置数据与当前正在使用的配置数据做比较,如果配置有变化就调用Spring CloudAPI刷新配置,即调用ContextRefresher对象的refresh方法。

Spring Cloud在刷新配置之前会发送一个EnvironmentChangeEvent事件,在刷新配置之后,会发送一个RefreshScopeRefreshedEvent事件。

在前面分析Spring Cloud实现动态配置的源码时,我们还漏考虑了一个问题。如果使用动态配置,那么,在应用程序启动时,应用容器(ApplicationContext)启动之前,肯定是需要能够从配置中心拉取一次配置,否则应用将启动不起来。

上一篇文章分析Spring Cloud应用的启动流程也是为本篇作铺垫的。

Spring Cloud应用启动流程:

PropertySourceLocatorSpring Cloud提供的一个接口,用于动态从配置中心拉取配置。

代码语言:javascript
复制
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方法,即从配置中心拉取配置。

动态配置的初始化流程:

  • 1、在Spring CloudBootstrap容器中注册PropertySourceLocator
  • 2、应用容器启动时,在准备应用上下文(prepareContext)阶段会发送一个ConfigurableApplicationContext事件,Spring Cloud监听ConfigurableApplicationContext事件,并在initialize方法中通过PropertySourceLocator从配置中心拉取配置;
  • 3、prepareContext阶段结束后,此时环境Environment中已经存在启动应用容器所需的配置了,往下refreshContext阶段就能正常启动应用容器;

PropertySourceLocator是注册到Bootstrap容器的,但可通过父工厂拿到PropertySourceLocator。如果PropertySourceLocator拉取配置失败,那么后续refresh应用容器将会失败,程序异常退出。

Spring Cloud Kubernetes Config源码分析

Spring Cloud Kubernetes实现动态配置的源码在spring-cloud-kubernetes-config模块。该模块也是一个starter包,在META-INF目录有个spring.factories文件。该文件中配置注册到应用容器的自动配置类ConfigReloadAutoConfiguration、以及注册到Spring CloudBootstrap容器中的配置类BootstrapConfiguration

代码语言:javascript
复制
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.kubernetes.config.reload.ConfigReloadAutoConfiguration

org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.kubernetes.config.BootstrapConfiguration

BootstrapConfiguration

通过上一篇的学习我们知道,spring.factories中注册的BootstrapConfiguration是注册到Bootstrap容器的,也就是Spring Boot启动的应用容器的父容器。Spring CloudBootstrap容器为Spring Boot启动应用容器提供前置条件,例如环境准备,完成Spring Boot启动应用容器所需要的条件。

BootstrapConfiguration中注册的Bean有:与Kubernetes交互的KubernetesClient、用于动态加载配置的ConfigMapPropertySourceLocator。用于确保在Spring Boot启动应用容器时能够从配置中心拉取到配置。

KubernetesClientSpring Cloud Kubernetes项目中的地位很高,也是最需要优先被创建的,因为它提供访问Kubernetes API的能力,只有通过它才能调用Kubernetes API实现服务发现、加载动态配置。这与web应用需要先启动tomcat才能接收到请求一样。

ConfigReloadAutoConfiguration

ConfigReloadAutoConfiguration中注册的Bean有:ConfigurationChangeDetectorConfigurationUpdateStrategy

这两个Bean都是spring-cloud-kubernetes-config模块为实现动态拉取配置提供的,并非是实现Spring Cloud的接口。spring-cloud-kubernetes-config模块只是实现Spring CloudPropertySourceLocator接口。

ConfigurationUpdateStrategy:动态配置的更新策略,支持RESTART_CONTEXTREFRESHSHUTDOWN

默认使用REFRESH策略,即调用Spring Cloud提供的ContextRefresherrefresh方法刷新环境,刷新带有@ConfigurationProperties@RefreshScope注释的beanRESTART_CONTEXT策略为重启,SHUTDOWN策略为停止应用进程。

可在bootstrap.yaml配置文件中配置使用的动态配置更新策略。

代码语言:javascript
复制
spring:
  cloud:
    kubernetes:
      reload:
        strategy: REFRESH

ConfigurationChangeDetector:动态配置改变探测器。用于实现动态感知配置的改变,只在探测到有配置信息改变时,才会调用更新策略(ConfigurationUpdateStrategy)更新配置。

Spring Cloud Kubernetes Config为我们提供两种动态感知配置改变的探测器,一种是定时轮询探测器(POLLING),另一种是基于事件监听的探测器(EVENT),后者类似于ZK的监听机制。默认使用的是EVENT

如果想使用定时轮询策略,可在bootstrap.yaml配置文件中添加如下配置。

代码语言:javascript
复制
spring:
  cloud:
    kubernetes:
      reload:
        mode: polling
        period: 5000

即使用定时轮询探测器,每5秒从配置中心拉取一次配置,也就是读取一次ConfigMap资源。被引用的每个ConfigMap资源都会被读取一次,所以叫轮询。

END

Spring Cloud Kubernetes动态配置的实现原理难点不在Spring Cloud Kubernetes Config模块是如何实现的,而在于理解Spring Cloud的动态配置刷新机制,以及Spring Cloud应用的启动流程、被@RefreshScope注解注释的Bean的动态代理的实现。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java艺术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • BootstrapConfiguration
  • ConfigReloadAutoConfiguration
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档