CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛

起底SpringCloudConfig的动态刷新机制,来瞅瞅?-永久免费的源码丞旭猿

源码级分析Spring Cloud Config这篇文章讲过Spring Cloud Config如何在应用启动时加载远程配置,但Spring Cloud Config更令人着迷的是它的动态刷新机制,应用可以在不重启的情况下实现应用配置的在上下文中被更新,我们称之为应用配置的动态刷新。

Spring Cloud Config数据流

我们通常采用两种方式动态的刷新应用配置,一种是让应用主动的拉取,另外一种是Config server端主动推送到应用端,我比较倾向于后者。因为应用主动拉取的话服务端很难区分哪些配置需要更新,哪些不需要更新,只有把新的配置内容全量的返回给应用,由应用端来刷新所有的应用配置。但是如果是服务端主动推送的,那么服务端就可以选择推送变更的配置,而应用端可以自定义配置刷新的处理器只刷新使用了更新的配置的Bean。影响范围会相对较小,避免一些因为动态刷新造成的副作用。

两种更新配置方式

这里我们设计服务端通过消息队列推送更新的配置到应用端,应用端消费消息来刷新配置,我们甚至可以利用消息队列的特性(比如RoecktMQ)通过消息的topci和tag来使刷新配置的维度粒度更细致,比如是刷新整个集群还是刷新某个节点,或者刷新部分节点。不过这个不是本文的重点,大家可以思考下这个设计思路。本文主要介绍应用端是如何自定义处理消息然后动态刷新配置的。

Spring Cloud Config框架的自带的刷新配置功能会在调用Refresh endpint期间刷新应用程序的应用上下文,这将停止当前应用程序包括正在运行的线程。

packageorg.springframework.cloud.endpoint;importjava.util.Collection;importjava.util.Set;importorg.springframework.boot.actuate.endpoint.annotation.Endpoint;importorg.springframework.boot.actuate.endpoint.annotation.WriteOperation;importorg.springframework.cloud.context.refresh.ContextRefresher;@Endpoint(
    id ="refresh")publicclassRefreshEndpoint{privateContextRefresher contextRefresher;publicRefreshEndpoint(ContextRefresher contextRefresher) {this.contextRefresher = contextRefresher;
    }@WriteOperationpublicCollection refresh() {// 调用refresh接口会触发动态刷新配置Set keys =this.contextRefresher.refresh();returnkeys;
    }
}

我们看到refresh方法里ContextRefresher的refresh()会执行应用上下文的刷新

public synchronizedSet<String> refresh() {Set<String> keys =this.refreshEnvironment();this.scope.refreshAll();returnkeys;
}








我们接着进一步看refresh方法里会调用的refreshEnvironment(),我们可以看到它会重新构建整个ApplicationContext,相当于一个应用重启,这样的动态刷新其实还是比较重的,即使我只改了一条配置都需要重启整个应用的上下文。

我们接着进一步看refresh方法里会调用的refreshEnvironment(),我们可以看到它会重新构建整个ApplicationContext,相当于一个应用重启,这样的动态刷新其实还是比较重的,即使我只改了一条配置都需要重启整个应用的上下文。

public synchronizedSet<String> refreshEnvironment() {Map<String,Object> before =this.extract(this.context.getEnvironment().getPropertySources());this.addConfigFilesToEnvironment();Set<String> keys =this.changes(before,this.extract(this.context.getEnvironment().getPropertySources())).keySet();this.context.publishEvent(newEnvironmentChangeEvent(this.context, keys));returnkeys;
}
 
ConfigurableApplicationContext addConfigFilesToEnvironment() {
    ConfigurableApplicationContext capture =null;
    boolean var15 =false;try{
        var15 =true;
        StandardEnvironment environment =this.copyEnvironment(this.context.getEnvironment());// 创建一个新的 spring application builderSpringApplicationBuilder builder = (newSpringApplicationBuilder(newClass[]{ContextRefresher.Empty.class})).bannerMode(Mode.OFF).web(WebApplicationType.NONE).environment(environment);
        builder.application().setListeners(Arrays.asList(newBootstrapApplicationListener(),newConfigFileApplicationListener()));//通过SpringApplicationBuild重新构建applicationcapture = builder.run(newString[0]);if(environment.getPropertySources().contains("refreshArgs")) {
            environment.getPropertySources().remove("refreshArgs");
        }
 
        MutablePropertySources target =this.context.getEnvironment().getPropertySources();StringtargetName =null;
        Iterator var6 = environment.getPropertySources().iterator();

所以我们只提取spring cloud的部分刷新功能,只在配置属性更新后重建bean,而不去重启整个应用上下文。假如我们是通过消费消息队列来处理动态刷新,那么我们可以在消息的Listener里添加自定义的处理器来实现这一点

protectedvoidhandleConfigChangeMessage(MessageExt messageExt)throwsInterruptedException, RemotingException, MQClientException, MQBrokerException{
    refreshConfig(messageExt);//只执行refreshScope.refreshAll() 方法,去除refreshEnvironment这一步,忘记在Listener里注入RefreshScoperefreshScope.refreshAll();
}privatevoidregreshConfig(){//解析Message成键值对//通过EnvironmentManager 更新上下文中的配置内容,别忘记在Listener里注入EnvironmentManeger}

RefreshScode的refreshAll方法会扫描项目中加了@RefreshScope的bean,然后重新构建bean,在构建过程中由于前一步已经把Environment中的配置更新了,所以构建的bean使用的就是新的配置了。

六不六,感觉六的就素质三连吧(点赞,收藏,转发)。不过这里其实有个副作用,篇幅有限,先卖个关子吧,没时间了,还得去喂狗。下次更新下这里面有什么坑,欢迎继续关注。

声明:本文部分素材转载自互联网,如有侵权立即删除 。

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
相关推荐
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容