Spring Cloud Config动态配置是如何实现的?
一,配置中心动态配置概述
Spring Cloud Config的动态配置需要借助Spring Cloud Bus来实现。如何实现的呢?我们先来看看思路:Spring Cloud Bus对外提供一个http接口,我们将这个接口配置到git上。当git上的文件内容发生变化时,就会自动调用我们定义的这个接口,然后Config Server就会重新从git获取最新的配置信息。Config Server把最新的配置信息放到消息队列中,Config Client订阅该消息,这样就实现了动态刷新配置信息的功能。
二,@RefreshScope注解
关于这个注解,官方是这样解释的:
Note that all beans in this scope are only initialized when first accessed, so the scope forces lazy initialization semantics. The implementation involves creating a proxy for every bean in the scope, so there is a flag.
If a bean is refreshed then the next time the bean is accessed a new instance is created. All lifecycle methods are applied to the bean instances, so any destruction callbacks that were registered in the bean factory are called when it is refreshed, and then the initialization callbacks are invoked as normal when the new instance is created. A new bean instance is created from the original bean definition, so any externalized content is re-evaluated when it is created.
这段话我就不再翻译了,原滋原味的,多读几遍,更能体会坐着作者的原意。实在不懂得,可以去使用浏览器搜索翻译一下。我们来看作者的代码是怎么写的。
@RefreshScope注解的处理类是RefreshScope.class,具体的刷新逻辑就是
RefreshScope.refresh(name)和RefreshScope.refreshAll()。
大致思路是这样的:拿到@RefreshScope注解的bean,清空bean缓存,这样下次执行bean时,就会重新生成bean了,这样就实现了这个bean下面的所有配置信息的自动刷新了。
注意这里的bean缓存是:
GenericScope.BeanLifecycleWrapperCache
并且在父类GenericScope中,还会对外暴露一个接口/refresh,修改配置以后,我们只要手动访问一下这个接口 就可以实现刷新配置的功能了。
调用RefreshScope的地方在哪里呢?
在这里:ContextRefresher.refresh()
源码如下:
// 判断PropertySource的实现是否是
// EnumerablePropertySource,如果是,则
//加入result并返回。
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(new EnvironmentChangeEvent(keys));
// 开启定时任务
this.scope.refreshAll();
// 把变更的配置的key组成的集合返回
return keys;
总结:@RefreshScope注解是如何实现自动刷新bean配置信息的呢?说白了,就是让bean失效,这样下次访问bean时,就会重新生成bean了。
但是,这里,我还有一个疑问:如果修改配置后,不去手动访问spring暴露的/refresh接口,下次访问@RefreshScope注解的bean时,能获取到最新的配置信息吗?
三,Spring Cloud Bus
什么是Spring Cloud Bus:轻量级的消息代理。从技术角度来说,Spring Cloud Bus使用了java的事件处理机制和MQ的部分特性。
Spring Cloud Bus的工作流程:
发送端:构造事件event,将其publish到applicationContext中,然后将事件发布到channel。
接收端:从channel中获取message,将message转为event,然后将event事件publish到applicationContext中,最后接收端收到event,调用服务进行逻辑处理。
publish:这里的publish是ApplicationEventPublisher
channel:这里的channel是MessageChannel
event:ApplicationEvent,具体实现有以下几种:
AckRemoteApplicationEvent
RefreshRemoteApplicationEvent
UnknownRemoteApplicationEvent
EnvironmentChangeRemoteApplicationEvent
具体的细节这里不再赘述,会另起文章讨论
Spring Cloud Bus,这里明白大概流程即可。
四,Git 之 WebHooks
什么是Webhooks呢?官方解释如下:
Webhooks allow external services to be notified when certain events happen. When the specified events happen, we’ll send a POST request to each of the URLs you provide.
翻译过来就是:
Webhooks允许在某些事件发生时通知外部服务。当指定的事件发生时,我们将向您提供的每个URLs发送一个POST请求。
借助Webhooks,我们就可以在git远程仓库的配置发生变化时,让git通知Config Server,从而实现自动刷新的功能。