前言
dubbo提供服务运行时动态修改配置的功能。
原理是服务消费方和服务提供方都注册时间,监听注册中心上某个服务暴露接口的configurator节点,通过dubbo提供的api注册override协议或者zookeeper api直接修改该节点的内容,客户端监听到之后把修改后的Url中的配置重写到内存中,以达到动态修改服务配置的目的。
imagedubbo override协议 :
RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&timeout=1000"));
事件注册时机
在服务提供方或者服务消费方注册服务之后,往zookeeper中的该节点注册监听时间。
源码
接着上一篇 服务暴露方注册服务之后
image1、URL从注册协议替换
第一行代码就会把协议从Registry换成provider协议,然后把协议的category属性换成configurator
image image替换后的url
provider://192.168.31.211:20880/com.lb.dubbo_api.service.UserService?anyhost=true&application=dubbo-p&bean.name=ServiceBean:com.lb.dubbo_api.service.UserService
&category=configurators
&check=false&dubbo=2.0.2&generic=false&interface=com.lb.dubbo_api.service.UserService&methods=getUser&pid=60975&side=provider×tamp=1626103040686
2. 创建OverrideListener对象
OverrideListener接口
dubbo抽象的监听器,只有一个notify方法,用来执行触发监听后执行业务逻辑的
image
OverrideListener类实现了上述接口,持有订阅事件的url协议和invoker对象
image通过构造器new,传入url协议和invoker对象
image放入缓存,url -> overrideListener实例的缓存
image3. 注册事件
目前只new出了dubbo的监听器实例,还没有注册到zookeper。
image3.1. 建立overrideListener和zookeeper监听器实例的映射
上面这行代码,调父类AbstractRegistry的subscribe建立缓存
image image
缓存映射关系
URL : ConcurrentHashSet<NotifyListener>
3.2. 注册事件核心
第一个判断不会走,因为我们的接口类是具体的接口,而不是 *
imageelse
又是一个缓存容器
image
url :{NotifyListener : ChildListener}
第一次进来根据NotifyListener肯定拿不到ChildListener实例,所以走创建
image3.2.1 ChildListener
只有一个childChanged方法
image
注意new ChildListener实例的时候,是把notifyListener传进去的
并且实现的childChanged方法,会调用传入的notifyListener的notify方法
image3.2.2 往zk创建configurator持久节点
zk节点路径
/dubbo/com.lb.dubbo_api.service.UserService/configurators
image
当然,里面会判断是否已存在此节点,没有才会创建
image3.2.3 注册zk事件
image一进来又是一个缓存容器
ChildListener : TargetChildListener(泛型)
image
创建curator的的CuratorWatcher时间监听实例
这里的TargetChildListener泛型在这里就是zk客户端curator的事件监听器实现类Watcher,因为后续就会往缓存容器中put :
childListener -> new CuratorWatcherImpl(childListener)
image
构造器中持有的是childListener
image这里就会掉用ChildListener事件的方法
image注册事件 :CuratorWatcherImpl
用Curator的api注册事件
image
事件触发监听调用流程
前面讲到
childerListener的childChanged会调用到overrideListener的Notity方法,并且持有了overrideListener实例
curator的事件监听实例CuratorWatcherImpl的process会响应监听,并且他持有了childerListener实例,process方法中会调用childerListener的childChanged方法。
所以整体的事件监听触发调用流程是这样的
首先zookeeper基于长链接,调用zk客户端的CuratorWatcherImpl的process方法,然后process方法调用childerListener的childChanged(),然后childChanged()去调用overrideListener的notify(),完成curator事件监听到dubbo事件监听的代码流转
CuratorWatcherImpl.process(event) ->
ChildListener.childChanged() ->
NotifyListener.notify()
最终根据zk configurator节点更新后的配置信息,去覆盖内存中的配置信息,都在NotifyListener.notify()实现的。
网友评论