Zookeeper Vorbereitung:
- Laden Sie die Zookeeper-Serverseite herunter (hier gibt es eine Grube, nicht apache-zookeeper-3.5.5.tar.gz): http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.5.5/apache- zookeeper- 3.5.5-bin.tar.gz
- Kopieren Sie {zookeeper_base} \ conf \ zoo_sample.cfg in das aktuelle Verzeichnis und benennen Sie es in zoo.cfg um
- Starten Sie {zookeeper_base} \ bin \ zkServer.cmd
Klassenvererbungsbeziehung:
- RegistryService bietet 5 Schnittstellen: Register registrieren (URL-URL), Registrierung aufheben (URL-URL), Abonnieren (URL-URL, NotifyListener-Listener), Abbestellen (URL-URL, NotifyListener-Listener), Nachschlagen (URL-URL).
- FailbackRegistry ist die Implementierungsklasse von RegistryService, die für das Wiederholen von Abonnementfehlern und Abmeldefehlern verantwortlich ist (versuchen Sie es regelmäßig mit zeitgesteuerten Aufgaben). Außerdem werden abstrakte Methoden wie doRegister (URL-URL), doUnregister (URL-URL), doSubscribe (URL-URL, NotifyListener-Listener) und doUnsubscribe (URL-URL, NotifyListener-Listener) definiert.
- ZookeeperRegistry ist die Implementierungsklasse der abstrakten FailbackRegistry-Klasse, die die Methoden zum Registrieren, Kündigen, Abonnieren und Kündigen implementiert.
Zookeeper ist eine Registrierung, die für die Registrierung und Ermittlung von Konfigurationsinformationen verantwortlich ist. In der Architektur von Dubbo handelt es sich um eine der Implementierungen der Dienstregistrierung und -erkennung, die hauptsächlich für die Offenlegung der Dienstschnittstelle verantwortlich ist. Durch die Knotenkonfiguration können Verbraucher Dienstanbieter finden. Lassen Sie uns den Quellcode von ZookeeperRegistry analysieren.
// 服务注册时,创建节点
protected void doRegister(URL url) {
try {
// ZookeeperClient zkClient
// 后面会解析
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);
}
}
// 服务解注册,删除节点
protected void doUnregister(URL url) {
try {
// ZookeeperClient zkClient
// 后面会解析
zkClient.delete(toUrlPath(url));
} catch (Throwable e) {
throw new RpcException("Failed to unregister " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
// 服务订阅
// ZookeeperRegistry#doSubscribe(final URL url, final NotifyListener listener)
protected void doSubscribe(final URL url, final NotifyListener listener) {
try {
if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
// 订阅所有节点
String root = toRootPath();
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) {
for (String child : currentChilds) {
child = URL.decode(child);
if (!anyServices.contains(child)) {
anyServices.add(child);
subscribe(url.setPath(child).addParameters(Constants.INTERFACE_KEY, child,
Constants.CHECK_KEY, String.valueOf(false)), listener);
}
}
}
});
zkListener = listeners.get(listener);
}
zkClient.create(root, false);
List<String> services = zkClient.addChildListener(root, zkListener);
if (services != null && !services.isEmpty()) {
for (String service : services) {
service = URL.decode(service);
anyServices.add(service);
subscribe(url.setPath(service).addParameters(Constants.INTERFACE_KEY, service,
Constants.CHECK_KEY, String.valueOf(false)), listener);
}
}
} else {
// 订阅部分节点
List<URL> urls = new ArrayList<URL>();
for (String path : toCategoriesPath(url)) {
// ConcurrentMap<URL, ConcurrentMap<NotifyListener, ChildListener>> zkListeners
// 一个URL有一个ConcurrentMap<NotifyListener, ChildListener>
// NotifyListener的实现类如RegistryDirectory
// ChildListener对RegistryDirectory配置变动的监听,在其childChanged()对业务进行处理
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);
// RegistryDirectory
if (zkListener == null) {
// 创建监听器,监听节点变化
listeners.putIfAbsent(listener, new ChildListener() {
@Override
public void childChanged(String parentPath, List<String> currentChilds) {
// 有变更时会调用RegistryDirectory#notify(List<URL>)
ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds));
}
});
zkListener = listeners.get(listener);
}
// 创建持久化节点
zkClient.create(path, false);
// 为节点添加监听
// 最终调用CuratorFramework#getChildren()#usingWatcher(listener)#forPath(path)进行监听
List<String> children = zkClient.addChildListener(path, zkListener);
if (children != null) {
urls.addAll(toUrlsWithEmpty(url, path, children));
}
}
// 订阅时,会调用RegistryDirectory#notify(List<URL>)初始化
notify(url, listener, urls);
}
} catch (Throwable e) {
throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
// 取消订阅
protected void doUnsubscribe(URL url, NotifyListener listener) {
ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
if (listeners != null) {
ChildListener zkListener = listeners.get(listener);
if (zkListener != null) {
if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
// 订阅所有节点
String root = toRootPath();
zkClient.removeChildListener(root, zkListener);
} else {
for (String path : toCategoriesPath(url)) {
// 删除监听
// ((CuratorWatcherImpl) listener).unwatch()
zkClient.removeChildListener(path, zkListener);
}
}
}
}
}
Werfen wir einen Blick auf die Vorgänge beim Erstellen, Löschen und Überwachen von Knoten in ZookeeperClient.
// 递归创建节点
// 除了叶节点是临时节点,其余节点都是永久节点(叶节点数据会定期更新可用的服务)
// eg. /dubbo/com.alibaba.dubbo.demo.DemoService/providers/dubbo%3A%2F%2F10.0.75.1%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26bean.name%3Dcom.alibaba.dubbo.demo.DemoService%26dubbo%3D2.0.2%26generic%3Dfalse%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26methods%3DsayHello%26pid%3D7160%26side%3Dprovider%26timestamp%3D1567860977014
// 创建节点有2种实现:CuratorZookeeperClient和ZkclientZookeeperClient,默认使用CuratorZookeeperClient实现
// AbstractZookeeperClient.create(String path, boolean ephemeral)
public void create(String path, boolean ephemeral) {
if (!ephemeral) {
// 非临时节点
if (checkExists(path)) {
// 已存在则不再创建
return;
}
}
int i = path.lastIndexOf('/');
if (i > 0) {
// 判断是否为最后一个
// 递归创建节点
create(path.substring(0, i), false);
}
if (ephemeral) {
// 创建临时节点
createEphemeral(path);
} else {
// 创建持久化节点
createPersistent(path);
}
}
// 为节点添加监听
public List<String> addChildListener(String path, final ChildListener listener) {
ConcurrentMap<ChildListener, TargetChildListener> listeners = childListeners.get(path);
if (listeners == null) {
childListeners.putIfAbsent(path, new ConcurrentHashMap<ChildListener, TargetChildListener>());
listeners = childListeners.get(path);
}
TargetChildListener targetListener = listeners.get(listener);
if (targetListener == null) {
listeners.putIfAbsent(listener, createTargetChildListener(path, listener));
targetListener = listeners.get(listener);
}
// 调用子类添加监听
// 默认实现是CuratorZookeeperClient#addTargetChildListener(path, targetListener)
return addTargetChildListener(path, targetListener);
}