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

原创 吴就业 128 0 2020-07-05

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/c199f9c21a824710942b24db2802911b

作者:吴就业
链接:https://wujiuye.com/article/c199f9c21a824710942b24db2802911b
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

本篇文章写于2020年07月05日,从公众号|掘金|CSDN手工同步过来(博客搬家),本篇为原创文章。

Spring Cloud Kubernetes微服务实战与源码分析

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动态配置的使用方式

关于如何使用动态配置以及监听配置改变,笔者在《Spring Cloud kubernetes入门项目sck-demo》这篇文章已经介绍了详细的使用步骤,本篇再对整个使用流程做个总结,概括使用步骤。

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

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
</dependency>

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

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

spring:
  cloud:
    kubernetes:
      reload:
        enabled: true
      config:
        ## 数组,引用的多个ConfigMap资源名称
        sources:
          - name: [ConfigMap资源名称]

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

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

如果有需要,你可以选择监听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提供的一个接口,用于动态从配置中心拉取配置。

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方法,即从配置中心拉取配置。

动态配置的初始化流程:

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

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配置文件中配置使用的动态配置更新策略。

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艺术”的水印。

文章推荐

OpenFeign整合Sentinel实现熔断降级

本篇先介绍如何将Sentinel与OpenFeign整合使用,并且熔断降级策略使用动态配置,将配置存储在配置中心。

玩转OpenFeign(下)

这篇主要介绍如何为不同的Client配置不同的连接超时、读超时这类参数,并从源码角度分析配置是怎么起作用的,以及都可以配置哪些参数,内容不多。

玩转OpenFeign(上)

使用OpenFeign不仅能够简化调用接口的步骤,也能顺便使用OpenFeign提供的重试机制,不需要再编写一个HttpUtils工具类。

Spring Boot与Spring Cloud应用启动流程

本篇我们一起学习Spring Boot与Spring Cloud应用的启动流程。

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

本篇从源码分析Spring Cloud实现动态配置的原理。Spring Cloud实现动态配置需要结合Spring源码分析。

Spring Cloud Kubernetes服务注册与发现实现原理与源码分析

本篇分析Spring Cloud Kubernetes服务注册与发现实现原理,以及Spring Cloud Kubernetes Core&Discovery源码分析。