上一章的中有講到ServiceBean在export的過程中向zk寫入的信息窥妇,這一章看下ReferenceBean在refer的過程中,向zk寫的數(shù)據(jù)娩践,已經(jīng)監(jiān)聽了哪些變更活翩。
我們直接的拉到ReferenceBean的getObject方法,如下
public Object getObject() throws Exception {
return get();
}
直接的跟到ReferenceConfig類的init方法里面的最重要的一句
ref = createProxy(map);
而在createProxy方法里面翻伺,最重要的一句材泄,如下
invoker = refprotocol.refer(interfaceClass, urls.get(0));
我們直接的跟到RegistryProtocol的refer方法里面的最后一句,如下
return doRefer(cluster, registry, type, url);
而在doRefer里面摘取重要的語句如下
//構(gòu)造url
URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, parameters.remove(Constants.REGISTER_IP_KEY), 0, type.getName(), parameters);
if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
&& url.getParameter(Constants.REGISTER_KEY, true)) {
URL registeredConsumerUrl = getRegisteredConsumerUrl(subscribeUrl, url);
//注冊消費(fèi)者信息
registry.register(registeredConsumerUrl);
directory.setRegisteredConsumerUrl(registeredConsumerUrl);
}
//訂閱指定zk目錄的信息
directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
Constants.PROVIDERS_CATEGORY
+ "," + Constants.CONFIGURATORS_CATEGORY
+ "," + Constants.ROUTERS_CATEGORY));
其中
registry.register(registeredConsumerUrl);
會(huì)調(diào)用到ZookeeperRegistry的doRegister方法吨岭,如下
protected void doRegister(URL url) {
try {
zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true));
} catch (Throwable e) {
throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
其中toUrlPath(url)返回如下
image.png
等于說我們在/dubbo/com.starunion.transport.service.TransportService/consumers目錄下添加了該dubbo服務(wù)的消費(fèi)者信息拉宗。
而
directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
Constants.PROVIDERS_CATEGORY
+ "," + Constants.CONFIGURATORS_CATEGORY
+ "," + Constants.ROUTERS_CATEGORY));
一直跟到ZookeeperRegistry的doSubscribe方法,核心代碼如下
for (String path : toCategoriesPath(url)) {
ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
if (listeners == null) {
zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
listeners = zkListeners.get(url);
}
ChildListener zkListener = listeners.get(listener);
if (zkListener == null) {
listeners.putIfAbsent(listener, new ChildListener() {
@Override
public void childChanged(String parentPath, List<String> currentChilds) {
ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds));
}
});
zkListener = listeners.get(listener);
}
zkClient.create(path, false);
List<String> children = zkClient.addChildListener(path, zkListener);
if (children != null) {
urls.addAll(toUrlsWithEmpty(url, path, children));
}
}
notify(url, listener, urls);
}
其中 toCategoriesPath(url)返回如下
image.png
所以消費(fèi)端訂閱的zk節(jié)點(diǎn)為 providers(實(shí)時(shí)的監(jiān)聽providers的變化),
configurators(實(shí)時(shí)的監(jiān)聽配置變化)旦事,routers(實(shí)時(shí)的監(jiān)聽路由配置的變化)
如果打開dubbo的后臺(tái)頁面的話魁巩,ReferenceBean關(guān)注的功能如下
image.png