Springcloud 服务配置与刷新是怎么工作的

今天我们来看一下Springcloud的服务配置与刷新是怎么工作的

通过这个理解我们可以做相应的扩展,例如如何像nacos/apollo那样编写自己工作需要的服务配置与刷新代码

先介绍一下核心的接口

PropertySource表示配置源

PropertySourceLocator表示配置源定位器(加载器)

启动配置加载

我们先来看Springboot启动时的配置加载过程,来看PropertySourceBootstrapConfiguration

它实现了ApplicationContextInitializer

在Springboot启动过程 Springboot 启动过程_icodegarden的博客-CSDN博客 中我们知道所有的ApplicationContextInitializer会在启动阶段的prepareContext中触发initialize

下面我们来看PropertySourceBootstrapConfigurationinitialize

这里的主要过程是

1、通过locator.locateCollection(environment)获取PropertySource,这里的locator就是PropertySourceLocator

2、把获取到的PropertySource加入到Environment

这样Springboot就准备好了Environment,其中包含配置中心的配置

现在我们来看PropertySourceLocator

以nacos为例看它的实现NacosPropertySourceLocator

看主要的loadApplicationConfiguration加载服务对应的配置

以上配置都是通过loadNacosDataIfPresent方法加载

最后通过configService.getConfig获取数据,内部的http请求不再详细展开

以上是Springboot启动阶段的配置加载过程

动态刷新

我们再来看配置动态刷新的过程,在触发方面没有统一的规范,不同的厂商有不同的方式,我们还是看nacos的实现,有个NacosContextRefresher

创建Listener

在Springboot启动过程 Springboot 启动过程_icodegarden的博客-CSDN博客 中我们知道ApplicationReadyEvent是在启动的最后阶段发出的,下面是收到Event后的处理

我们可以看到这里创建了一个Listener,并且configService.addListener,这里创建的Listener将在后面触发回调,暂且不提,我们看configService有什么内容

来到NacosContextRefresher的构造方法

configService是在这里被创建的

NacosConfigService的构造方法

构造方法中又创建了ClientWorker

ClientWorker中开启了checkConfigInfo的调度

长轮询配置变更

重点来了,这里创建了LongPollingRunnable的任务,下面展示run方法中的关键部分

这段是检查本地配置是否有变化,有变化则在cacheData.checkListenerMd5();中触发之前创建的Listener

这段做3个事情

1、使用http long poll(长轮询,这里默认的Long-Pulling-Timeout是30000ms,read timeout是45000ms)检查nacos server端的配置是否有变化,返回有变化的keys

2、有变化的则获取新的配置

3、在cacheData.checkListenerMd5();中触发之前创建的Listener

最后这段是让LongPollingRunnable保持循环执行

通知Listener

我们继续看cacheData.checkListenerMd5();

本地维护的缓存MD5值由变化则表示配置有变,然后执行listener.receiveConfigInfo(contentTmp);

现在我们要回到之前所创建的Listener了

这里发出了RefreshEvent

刷新配置

继续来看RefreshEvent的监听器RefreshEventListener

这里的refreshContextRefresher,所做的工作是配置刷新,RefreshEventListener的完整类名是org.springframework.cloud.endpoint.event.RefreshEventListener,是Spring所定义的,之后的配置刷新过程的代码与配置中心厂商就无关了

我们继续进去看

refreshEnvironment即刷新context的Environment,updateEnvironment有2种实现

LegacyContextRefresherConfigDataContextRefresher

LegacyContextRefresher的过程是通过启动一次模拟的Application来加载完整的配置给新的Environment,加载同样也使用PropertySourceLocator(实现类例如NacosPropertySourceLocator),这里整个过程无需厂商再实现其他接口

ConfigDataContextRefresher的过程则需要厂商再实现相应的接口规范

最后使用this.scope.refreshAll();来达到刷新配置的目的

@Value的值就放在StandardScopeCache

刷新原理AOP

奇怪的是我们看到的是把cache清理了,而没有看到诸如把配置值的进行替换的代码,为什么我们获取到的@Value的值就是新的了呢

其实奥秘还是在Spring的AOP中,当我们的请求访问有@RefreshScope的bean的方法时,首先会经过AOP的chain,关于AOP我们可以回顾 Spring AOP是怎么工作的_icodegarden的博客-CSDN博客 ,而chain中的其中一个MethodInterceptorLockedScopedProxyFactoryBean

这里将会先访问GenericScopeget(String name, ObjectFactory<?> objectFactory)

最后访问StandardScopeCache的以下方法

当配置更新后,就会触发上述的@Value缓存值清理,因此再来访问时就没有对应的值了,会把新的值设置到缓存中,于是最终我们获取到的@Value值是新的

以上就是Springboot配置的动态刷新过程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值