上一章的中有讲到ServiceBean在export的过程中向zk写入的信息,这一章看下ReferenceBean在refer的过程中,向zk写的数据,已经监听了哪些变更。
我们直接的拉到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里面摘取重要的语句如下
//构造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);
//注册消费者信息
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);
会调用到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服务的消费者信息。
而
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
所以消费端订阅的zk节点为 providers(实时的监听providers的变化),
configurators(实时的监听配置变化),routers(实时的监听路由配置的变化)
如果打开dubbo的后台页面的话,ReferenceBean关注的功能如下
image.png
网友评论