一.前言.
Nocos( Dynamic Naming and Configuration Service)是阿里开源的,集配置中心和注册中心为一体的微服务框架.
此篇主要说明Nacos在作为配置中心时是怎样做到动态更新配置的.
二.实现方式猜想
其实要实现动态配置更新,目前主要有两种方式:
- 客户端每隔一段时间进行定时加载配置,这种很容易实现,但是性能不高,并且在一定时间范围内无法做到及时更新.
- 服务端在发生配置变更的时候向客户端发起一个通知,客户端收到通知后,去加载变更的配置.这种比较高效.
三.Nocas具体实现
nacos是第二种思想.
SDK(也就是客户端) 通过 GRPC(一个开源RPC框架,用于服务调用) 长连接监听配置变更,Server 端对比 Client 端配置的 MD5 和本地 MD5是否相等,不相等推送配置变更.
四.如何动态更新bean的呢?
在服务端发送通知,客户端拿到最新的配置后,通常需要动态更新一些bean,那是怎么做的呢?
- 首先标识需要动态更新的bean对象.
使用SpringCloud中的@RefreshScope注解,这个注解主要有两个作用.
(1) @Scope(“refresh”):将其作用域标识为特殊的refresh
(2) ScopedProxyMode.TARGET_CLASS :当ScopedProxyMode 为TARGET_CLASS 的时候会给当前创建的bean 生成一个代理对象,会通过代理对象来访问(这个后面会重点说明) - 客户端拿到最新的配置后,将配置更新到Spring容器中的Environment对象中.
- 清除bean缓存,这里的缓存和通常说的三级缓存有点不一样,是BeanLifecycleWrapperCache,缓存了所有@RefreshScope 标注的对象.
- 对所有需要动态更新的bean重新执行实例化,初始化的过程,执行完毕重新放到缓存中.
补充知识:
在IOC容器里面,有一个map类型的scopes的缓存,他会根据scope名称不同,分为restart、request、session、refresh、application(至于为啥没有单例和多例,因为单例的缓存已经单独放在SingletonObjects缓存里面了,多例就更不用说,压根就不需要缓存)。
五.原理细节理解
问题1:
当某个对象加了@RefreshCode注解,一旦该对象的某个值要更新,那么所有依赖到该对象的对象也需要更新,那是怎么做的呢?难道全部都从新实例化初始化吗?要是这样的话就有些不合理了.
答案:
其实Spring这里设计的还是很巧妙的.
正常来讲,Spring管理的所有对象的属性注入在项目一启动就已经确定了,那在启动后如果想更新某个对象值,不仅要更新本对象,还要更新所有依赖到该对象的对象.
那为了简化操作,Spring在依赖对象和属性之间加了一层代理,就是前面提到的ScopedProxyMode.TARGET_CLASS.当有对象标识为这个的时候,那么所有用到该对象的地方拿到的其实都是一个代理.
举例:
定义一个测试类:TestController.加了@RefreshScope注解,也就标识了ScopedProxyMode.TARGET_CLASS.
当TestController被其他类作为属性注入时,就会注入一个代理类.
当使用代理类去执行我们自己的方法的时候,会进入代理方法中,在代理方法中会去获取真正的对象.
在此方法getTarget()中,会根据不同情况判断是新增还是从缓存中获取对象.
假如是单例模式:会直接从一级缓存(SingletonObjects)中获取
假如是多例:直接重新走实例化初始化的过程
假如是其他:比如说是refresh,会从对应的缓存(BeanLifecycleWrapperCache)中获取.如下图.
那么当testController动态更新后,BeanLifecycleWrapperCache缓存中会对该对象进行更新,此时依赖到该对象的对象也能够获取到最新的对象,做到动态更新bean及其关联方.
这也是为什么如果某个对象加了refreshScope注解,那么该对象放到singletonObjects缓存中的就是一个代理对象,真正的对象在Scope.refresh.BeanLifecycleWrapperCache中.
问题2:
使用@RefreshScope的对象是单例的还是多例的?
答案:
可能是单例的,也可能是多例的.这取决于该对象有没有被动态更新过,如果更新过,那么其他bean获取到的该对象也就变了.否则,一直是同一个对象.
======================================================================================================
如果你需要阅读专业书籍来提升自己,可以关注博主的公众号,回复 图书即可获得几百本程序员必读书籍.
包含以下所有分类中的各种经典书籍.
今天的分享就到这里了,有问题可以在评论区留言,均会及时回复呀.
我是bling,未来不会太差,只要我们不要太懒就行, 咱们下期见.