前言
上一篇已经讲到服务提供者 注册完之后,会往zk节点 /dubbo/接口名/configurator节点注册监听事件,当该节点发生变化时,会调用NotifyListener监听器实例的notify方法来调用重载配置信息的逻辑。
1. 注册事件后,自动触发调用notify()
在注册完对/dubbo/接口名/configurator节点的监听事件
后,手动的调用一次notify()方法
首先利用这个方法往urls一个基于原url生成empty的协议
![](https://img.haomeiwen.com/i23353704/665bab0c0d210192.png)
把传入的url改成empty协议头
![](https://img.haomeiwen.com/i23353704/1d59b04a8286fff1.png)
如果注册监听事件之后返回的configurator节点下已有数据,也会获取到放在这个urls里面
![](https://img.haomeiwen.com/i23353704/45b345ec5f5b60fd.png)
![](https://img.haomeiwen.com/i23353704/c76233b14e350a5c.png)
每一个configurator的元素都会返回一个url放入到urls中
![](https://img.haomeiwen.com/i23353704/e67bba9b25fb40d7.png)
进入notify()
![](https://img.haomeiwen.com/i23353704/661695a37cd0d988.png)
![](https://img.haomeiwen.com/i23353704/bb9b6afca13d9ce4.png)
如果匹配的话,放到一个局部的map。
category : List<匹配的url>
这时候肯定是匹配的,因为新生成的empty的url就是根据原url改了protocol得来的
![](https://img.haomeiwen.com/i23353704/a13324f9274cf55c.png)
又有一个缓存容器
ConcurrentMap<URL, Map<String, List<URL>>> notified :
{url : {"configurator" : List<Url>}}
![](https://img.haomeiwen.com/i23353704/fd875d02d0a60490.png)
一开始肯定根据url拿不到,直接新建,并把result放到复制到url的map中
![](https://img.haomeiwen.com/i23353704/2597be2092ffdab6.png)
放完之后是这样的
![](https://img.haomeiwen.com/i23353704/804e6b038394a997.png)
把这几个configurator的协议写到本地文件中
![](https://img.haomeiwen.com/i23353704/6b29a851ae05e761.png)
调用 dubbo监听器的方法
![](https://img.haomeiwen.com/i23353704/ed5e49ef2d7d402a.png)
listener.notify(categoryList) 核心
1.根据匹配到的url 获取Configurator对象
![](https://img.haomeiwen.com/i23353704/3aba23ec41152418.png)
这里有一个重点,如果传入的url中有一个empty协议,就会清空list,返回空的configurators list
![](https://img.haomeiwen.com/i23353704/d5b5d607460be5f9.png)
否则对应每一个非empty url的生成一个Configurator对象
![](https://img.haomeiwen.com/i23353704/5e7fa79e99f39dcc.png)
2. 获取原始的的dubbo协议url
![](https://img.haomeiwen.com/i23353704/2be7dedb424cc661.png)
3. 通过configurators对象对原来的dubbo协议url进行修改,覆盖,生成新的url,由于这里自动调用notify,传入的empty协议,并不会去对原来的url进行修改
![](https://img.haomeiwen.com/i23353704/9a92c38290dfd2af.png)
![](https://img.haomeiwen.com/i23353704/b83c5477adb3e4a4.png)
2. 监听override协议,生成新的url
测试代码
利用dubbo的Registry api往configurator节点下写入override协议
@RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试
@ContextConfiguration(classes = {AnnoBean.class})
public class SpiTest {
@Test
public void testOverride(){
RegistryFactory registryFactory =ExtensionLoader.getExtensionLoader(Reistr yFactory.class).getAdaptiveExtenson();
Registry registry =registryFactory.getRegistry(URL.valuef("z ookeeper://maomaoyu.xyz:2181"));
registry.register(URL.valueOf("overrie://0 .0.0.0/com.lb.dubbo_api.service.serService ?category=configurators&dynmic=false&appli cation=foo&timeout=200"));
}
}
测试代码跑完,configurator节点出现我们刚写入的override协议
![](https://img.haomeiwen.com/i23353704/d9cc80e93b4c1cf5.png)
这个时候,之前注册的事件监听器就会被调到.
![](https://img.haomeiwen.com/i23353704/8241cdb7530cde71.png)
走的代码跟第一点讲的他自动调的那一次监听器一样的流程
![](https://img.haomeiwen.com/i23353704/549b57a4e5b21003.png)
![](https://img.haomeiwen.com/i23353704/db32c4f2182b214d.png)
同样的再调到监听器的notify方法,只不过这次由于没有empty协议,获取到的configurators有值了
![](https://img.haomeiwen.com/i23353704/c4e1b4b13a39a082.png)
configurators有值之后,会根据这个列表对原来的url进行覆盖,生成新的newUrl
url被override url覆盖
![](https://img.haomeiwen.com/i23353704/16537971b2acb802.png)
这里会有一个比较重要的判断
如果是当前监听到配置信息变更的服务实例的角色为消费者,那么会进行本机地址和override协议指定的地址进行判断,如果相等才会更新当前实例的配置信息。因为这个事件监听,所有该服务接口的消费者和生产者都会注册,都会接到变更的通知。
而生产者则不用判断本机地址和override协议指定的地址是否一直
![](https://img.haomeiwen.com/i23353704/b67a05bba39a37fe.png)
![](https://img.haomeiwen.com/i23353704/65be9c95d0269329.png)
==这就说明,更新配置信息 如果是对消费端的话,是针对ip更新某一台服务实例,如果是针对生产端的话,是更新所有生产方的配置信息==
生成新的url
![](https://img.haomeiwen.com/i23353704/f58464eb5bc3d934.png)
对其他的属性进行覆盖
![](https://img.haomeiwen.com/i23353704/0ac5da0df6969f69.png)
2. 根据生成的新的url,重新创建export对象
判断新url是否和原来的url是否相同
![](https://img.haomeiwen.com/i23353704/f19824f3f4e1afb8.png)
不相同,根据invoker对象和新url创建新的Exporter对象
![](https://img.haomeiwen.com/i23353704/56bf261badad9d1b.png)
接下来的代码和服务发布的时候,创建export对象是一样的
网友评论