1.ZookeeperRegister模块简介
本文章针对Zookeeper注册中心,注册,订阅源码设计导读;至于Zookeeper的优势,特点我们不做太多讲解;
下图为zookeeper存放数据的原理,为树状;因此我们这个模块本质要做的就是:
- 将Zookeeper的数据存放,删除:Dubbo集成CuratorFramework,客户端可以对Redis进行连接,删除,修改,新增节点,添加监听器等操作,来满足我们的业务需求;
数据结构分析:
- dubbo的Root层是根目录,通过<dubbo:registry group="dubbo" />的“group”来设置zookeeper的根节点,默认是“dubbo”。
- Service层是服务接口的全名。
- Type层是分类,一共有四种分类,分别是providers(服务提供者列表)、consumers(服务消费者列表)、routes(路由规则列表)、configurations(配置规则列表)。
- URL层:根据不同的Type目录:可以有服务提供者 URL 、服务消费者 URL 、路由规则 URL 、配置规则 URL 。不同的Type关注的URL不同。
ZookeeperRegistry
这个类继承FailbackRegistry,在原本的重试机制等下进行了Zoookeeper注册中心的实现;
基本属性:
// 日志输出
private final static Logger logger = LoggerFactory.getLogger(ZookeeperRegistry.class);
// 默认根节点
private final static String DEFAULT_ROOT = "dubbo";
// 就是group
private final String root;
// 服务集合
private final Set<String> anyServices = new ConcurrentHashSet<>();
// 监听器集合
private final ConcurrentMap<URL, ConcurrentMap<NotifyListener, ChildListener>> zkListeners = new ConcurrentHashMap<>();
// zk客户端,默认为CuratorFramework
private final ZookeeperClient zkClient;
初始化方法:
public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
super(url);
if (url.isAnyHost()) {
throw new IllegalStateException("registry address == null");
}
// 获取group信息,默认为"dubbo"
String group = url.getParameter(GROUP_KEY, DEFAULT_ROOT);
// group->/group
if (!group.startsWith(PATH_SEPARATOR)) {
// /dubbo开头
group = PATH_SEPARATOR + group;
}
this.root = group;
// 客户端连接
zkClient = zookeeperTransporter.connect(url);
// 监听状态
zkClient.addStateListener((state) -> {
if (state == StateListener.RECONNECTED) {
logger.warn("Trying to fetch the latest urls, in case there're provider changes during connection loss.\n" +
" Since ephemeral ZNode will not get deleted for a connection lose, " +
"there's no need to re-register url of this instance.");
ZookeeperRegistry.this.fetchLatestAddresses();
} else if (state == StateListener.NEW_SESSION_CREATED) {
logger.warn("Trying to re-register urls and re-subscribe listeners of this instance to registry...");
try {
ZookeeperRegistry.this.recover();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
} else if (state == StateListener.SESSION_LOST) {
logger.warn("Url of this instance will be deleted from registry soon. " +
"Dubbo client will try to re-register once a new session is created.");
} else if (state == StateListener.SUSPENDED) {
} else if (state == StateListener.CONNECTED) {
}
});
}
public boolean isAvailable()存活,public void destroy()销毁方法
@Override
public boolean isAvailable() {
return zkClient.isConnected();
}
@Override
public void destroy() {
// 调用父类方法
super.destroy();
try {
// 关闭连接
zkClient.close();
} catch (Exception e) {
logger.warn("Failed to close zookeeper client " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
注册,取消注册方法:调用zookeeper客户端进行删除,增加节点
@Override
public void doRegister(URL url) {
try {
// 创建节点
zkClient.create(toUrlPath(url), url.getParameter(DYNAMIC_KEY, true));
} catch (Throwable e) {
throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
@Override
public void doUnregister(URL url) {
try {
// 删除节点
zkClient.delete(toUrlPath(url));
} catch (Throwable e) {
throw new RpcException("Failed to unregister " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
订阅方法:public void doSubscribe(final URL url, final NotifyListener listener)
@Override
public void doSubscribe(final URL url, final NotifyListener listener) {
try {
// 如果是订阅所有Service,监控中心就会
if (ANY_VALUE.equals(url.getServiceInterface())) {
String root = toRootPath();
// 获取url监听器
ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
// 初始化监听器集合
if (listeners == null) {
zkListeners.putIfAbsent(url, new ConcurrentHashMap<>());
listeners = zkListeners.get(url);
}
// 节点监听器
ChildListener zkListener = listeners.get(listener);
if (zkListener == null) {
// 创建监听器:
listeners.putIfAbsent(listener, (parentPath, currentChilds) -> {
for (String child : currentChilds) {
child = URL.decode(child);
// 如果没有这个节点,添加,然后订阅
if (!anyServices.contains(child)) {
anyServices.add(child);
subscribe(url.setPath(child).addParameters(INTERFACE_KEY, child,
Constants.CHECK_KEY, String.valueOf(false)), listener);
}
}
});
zkListener = listeners.get(listener);
}
// 创建serive节点
zkClient.create(root, false);
List<String> services = zkClient.addChildListener(root, zkListener);
if (CollectionUtils.isNotEmpty(services)) {
for (String service : services) {
service = URL.decode(service);
anyServices.add(service);
subscribe(url.setPath(service).addParameters(INTERFACE_KEY, service,
Constants.CHECK_KEY, String.valueOf(false)), listener);
}
}
} else {
List<URL> urls = new ArrayList<>();
for (String path : toCategoriesPath(url)) {
ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
if (listeners == null) {
zkListeners.putIfAbsent(url, new ConcurrentHashMap<>());
listeners = zkListeners.get(url);
}
// 添加监听器
ChildListener zkListener = listeners.get(listener);
if (zkListener == null) {
listeners.putIfAbsent(listener, (parentPath, 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);
}
} catch (Throwable e) {
throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
取消订阅:
@Override
public 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 (ANY_VALUE.equals(url.getServiceInterface())) {
String root = toRootPath();
zkClient.removeChildListener(root, zkListener);
} else {
for (String path : toCategoriesPath(url)) {
zkClient.removeChildListener(path, zkListener);
}
}
}
}
}
LookUp
@Override
public List<URL> lookup(URL url) {
if (url == null) {
throw new IllegalArgumentException("lookup url == null");
}
try {
List<String> providers = new ArrayList<String>();
// 遍历分组类别
for (String path : toCategoriesPath(url)) {
// 获得子节点
List<String> children = zkClient.getChildren(path);
if (children != null) {
providers.addAll(children);
}
}
// 获得 providers 中,和 consumer 匹配的 URL 数组
return toUrlsWithoutEmpty(url, providers);
} catch (Throwable e) {
throw new RpcException("Failed to lookup " + url + " from zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
ZookeeperRegisterFactory
工厂模式
public class ZookeeperRegistryFactory extends AbstractRegistryFactory {
private ZookeeperTransporter zookeeperTransporter;
/**
* Invisible injection of zookeeper client via IOC/SPI
* @param zookeeperTransporter
*/
public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
this.zookeeperTransporter = zookeeperTransporter;
}
@Override
public Registry createRegistry(URL url) {
return new ZookeeperRegistry(url, zookeeperTransporter);
}
}
总结:
- zookeeperRegister实现了Zookeeper注册中心的注册,订阅等等行为实现;
- 针对于Zkclient后续通信模块会讲述;


1895

被折叠的 条评论
为什么被折叠?



