Preparação do Zookeeper:
- Baixe o lado do servidor Zookeeper (há um poço aqui, não baixe 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
- Copie {zookeeper_base} \ conf \ zoo_sample.cfg para o diretório atual e renomeie-o para zoo.cfg
- Inicie {zookeeper_base} \ bin \ zkServer.cmd
Relação de herança de classe:
- RegistryService fornece 5 interfaces: registrar registrar (URL url), cancelar o registro, cancelar o registro (URL url), inscrever-se (URL url, ouvinte NotifyListener), cancelar a inscrição (URL url, NotifyListener ouvinte), pesquisa (URL url).
- FailbackRegistry é a classe de implementação de RegistryService, que é responsável por tentar novamente as falhas de assinatura e de cancelamento de assinatura (tente periodicamente usando tarefas cronometradas). Ele também define métodos abstratos doRegister (URL url), doUnregister (URL url), doSubscribe (URL url, ouvinte NotifyListener), doUnsubscribe (url URL, ouvinte NotifyListener).
- ZookeeperRegistry é a classe de implementação da classe abstrata FailbackRegistry, que implementa os métodos de registro, cancelamento, assinatura e cancelamento.
Zookeeper é um registro, responsável pelo registro e descoberta de informações de configuração. Na arquitetura do dubbo, é uma das implementações de registro e descoberta de serviço, que é o principal responsável pela exposição da interface do serviço.Através da configuração do nó, o consumidor pode encontrar provedores de serviço. Vamos analisar o código-fonte do ZookeeperRegistry.
// 服务注册时,创建节点
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);
}
}
}
}
}
Vamos dar uma olhada nas operações de criação, exclusão e monitoramento de nós do 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);
}