百度:" ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集,提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在$zookeeper_home\src\recipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。"
在 dubbo-remoting-zookeeper 模块,实现了 Dubbo 对 Zookeeper 客户端的封装。在该模块中,抽象了通用的 Zookeeper Client API 接口,实现了两种 Zookeeper Client 库的接入:
<dubbo:registry address="zookeeper://127.0.0.1:2181" client="curator" />
<dubbo:registry address="zookeeper://127.0.0.1:2181" client="zkclient" />
com.alibaba.dubbo.remoting.zookeeper.StateListener ,状态监听器接口:
public interface StateListener {
/**
* 状态 - 已断开
*/
int DISCONNECTED = 0;
/**
* 状态 - 已连接
*/
int CONNECTED = 1;
/**
* 状态 - 已重连
*/
int RECONNECTED = 2;
/**
* 状态变更回调
*
* @param connected 状态
*/
void stateChanged(int connected);
}
ChildListener,节点监听器接口:
public interface ChildListener {
/**
* 子节点发生变化的回调
*
* @param path 节点
* @param children 最新的子节点列表
*/
void childChanged(String path, List<String> children);
}
ZookeeperClient ,Zookeeper 客户端接口:
public interface ZookeeperClient {
/**
* 创建节点
*
* @param path 节点路径
* @param ephemeral 是否临时节点
*/
void create(String path, boolean ephemeral);
/**
* 删除节点
*
* @param path 节点路径
*/
void delete(String path);
List<String> getChildren(String path);
/**
* 添加 ChildListener
*
* @param path 节点路径
* @param listener 监听器
* @return 子节点列表
*/
List<String> addChildListener(String path, ChildListener listener);
/**
* 移除 ChildListener
*
* @param path 节点路径
* @param listener 监听器
*/
void removeChildListener(String path, ChildListener listener);
/**
* 添加 StateListener
*
* @param listener 监听器
*/
void addStateListener(StateListener listener);
/**
* 移除 StateListener
*
* @param listener 监听器
*/
void removeStateListener(StateListener listener);
/**
* @return 是否连接
*/
boolean isConnected();
/**
* 关闭
*/
void close();
/**
* @return 获得注册中心 URL
*/
URL getUrl();
}
/*状态相关方法
isConnected()
close()
getUrl()
数据相关方法
create(path, ephemeral)
getChildren(path)
从 API 上,Dubbo 只使用节点的路径,而不使用节点的值(内容)。
监听相关方法
addChildListener(path, listener)
removeChildListener(path, listener)
addStateListener(listener)
removeStateListener(listener)*/
AbstractZookeeperClient ,实现 ZookeeperClient 接口,Zookeeper 客户端抽象类,实现通用的逻辑:
属性:
public abstract class AbstractZookeeperClient<TargetChildListener> implements ZookeeperClient {
/**
* 注册中心 URL
*/
private final URL url;
/**
* StateListener 集合
*/
private final Set<StateListener> stateListeners = new CopyOnWriteArraySet<StateListener>();
/**
* ChildListener 集合
*
* key1:节点路径
* key2:ChildListener 对象
* value :监听器具体对象。不同 Zookeeper 客户端,实现会不同。
*/
private final ConcurrentMap<String, ConcurrentMap<ChildListener, TargetChildListener>> childListeners = new ConcurrentHashMap<String, ConcurrentMap<ChildListener, TargetChildListener>>();
/**
* 是否关闭
*/
private volatile boolean closed = false;
public AbstractZookeeperClient(URL url) {
this.url = url;
}
@Override
public URL getUrl() {
return url;
}
// ... 省略其他方法
}
@Override
public void create(String path, boolean ephemeral) {
// 循环创建父路径
int i = path.lastIndexOf('/');
if (i > 0) {
String parentPath = path.substring(0, i);
if (!checkExists(parentPath)) {
create(parentPath, false);
}
}
// 创建临时节点
if (ephemeral) {
createEphemeral(path);
// 创建持久节点
} else {
createPersistent(path);
}
}
checkExists(path) 抽象方法,节点是否存在:
protected abstract boolean checkExists(String path);
createEphemeral(path) 抽象方法,创建临时节点:
protected abstract void createPersistent(String path);
createPersistent(path) 抽象方法,创建持久节点:
protected abstract void createEphemeral(String path);
StateListener 相关方法:
@Override
public void addStateListener(StateListener listener) {
stateListeners.add(listener);
}
@Override
public void removeStateListener(StateListener listener) {
stateListeners.remove(listener);
}
public Set<StateListener> getSessionListeners() {
return stateListeners;
}
/**
* StateListener 数组,回调
*
* @param state 状态
*/
protected void stateChanged(int state) {
for (StateListener sessionListener : getSessionListeners()) {
sessionListener.stateChanged(state);
}
}
ChildListener 相关方法:
@Override
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);
}
// 向 Zookeeper ,真正发起订阅
return addTargetChildListener(path, targetListener);
}
@Override
public void removeChildListener(String path, ChildListener listener) {
ConcurrentMap<ChildListener, TargetChildListener> listeners = childListeners.get(path);
if (listeners != null) {
TargetChildListener targetListener = listeners.remove(listener);
if (targetListener != null) {
// 向 Zookeeper ,真正发起取消订阅
removeTargetChildListener(path, targetListener);
}
}
}
createTargetChildListener(path, listener) 抽象方法,创建真正的 ChildListener 对象。因为,每个 Zookeeper 的库,实现不同:
protected abstract TargetChildListener createTargetChildListener(String path, ChildListener listener);
addTargetChildListener(path, targetListener) 抽象方法,向 Zookeeper ,真正发起订阅:
protected abstract List<String> addTargetChildListener(String path, TargetChildListener listener);
removeTargetChildListener(path, targetListener) 抽象方法,向 Zookeeper ,真正发起取消订阅:
protected abstract void removeTargetChildListener(String path, TargetChildListener listener);
close:
@Override
public void close() {
if (closed) {
return;
}
closed = true;
try {
doClose();
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
}
doClose() 抽象方法,关闭 Zookeeper 连接:
protected abstract void doClose();
ZookeeperTransporter,Zookeeper 工厂接口:
// @SPI("curator") 注解,使用 Dubbo SPI 机制,默认使用 Curator 实现。
@SPI("curator")
public interface ZookeeperTransporter {
/**
* 连接创建 ZookeeperClient 对象
*
* @param url 注册中心地址
* @return ZookeeperClient 对象
*/
@Adaptive({
Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})
ZookeeperClient connect(URL url);
// connect(url) 方法,连接创建 ZookeeperClient 对象。
// @Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY}) 注解,使用 Dubbo SPI Adaptive 机制,根据 url 参数,加载对应的 ZookeeperTransporter 拓展实现类。
}
CuratorZookeeperClient,实现 ZookeeperTransporter 抽象类,基于 Curator 的 Zookeeper 客户端实现类。
属性:
/**
* client 对象
*/
private final CuratorFramework client;
public CuratorZookeeperClient(URL url) {
super(url);
try {
// 创建 client 对象
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
.connectString(url.getBackupAddress()) // 连接地址
.retryPolicy(new RetryNTimes(1, 1000)) // 重试策略,1 次,间隔 1000 ms
.connectionTimeoutMs(5000); // 连接超时时间
String authority = url.getAuthority();
if (authority != null && authority.length() > 0) {
builder = builder.authorization("digest", authority.getBytes());
}
client = builder.build();
// 添加连接监听器
client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
public void stateChanged(CuratorFramework client, ConnectionState state) {
if (state == ConnectionState.LOST) {
CuratorZookeeperClient.this.stateChanged(StateListener.DISCONNECTED);
} else if (state == ConnectionState.CONNECTED) {
CuratorZookeeperClient.this.stateChanged(StateListener.CONNECTED);
} else if (state == ConnectionState.RECONNECTED) {
CuratorZookeeperClient.this.stateChanged(StateListener.RECONNECTED);
}
}
});
// 启动 client
client.start();
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
在连接状态发生变化时,调用 stateChange(state) 方法,进行 StateListener 的回调。
ChildListener 相关方法:
public CuratorWatcher createTargetChildListener(String path, ChildListener listener) {
return new CuratorWatcherImpl(listener);
}
public List<String> addTargetChildListener(String path, CuratorWatcher listener) {
try {
return client.getChildren().usingWatcher(listener).forPath(path);
} catch (NoNodeException e) {
return null;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
public void removeTargetChildListener(String path, CuratorWatcher listener) {
((CuratorWatcherImpl) listener).unwatch();
}
private class CuratorWatcherImpl implements CuratorWatcher {
private volatile ChildListener listener;
public CuratorWatcherImpl(ChildListener listener) {
this.listener = listener;
}
public void unwatch() {
this.listener = null;
}
@Override
public void process(WatchedEvent event) throws Exception {
if (listener != null) {
String path = event.getPath() == null ? "" : event.getPath();
listener.childChanged(path,
// if path is null, curator using watcher will throw NullPointerException.
// if client connect or disconnect to server, zookeeper will queue
// watched event(Watcher.Event.EventType.None, .., path = null).
StringUtils.isNotEmpty(path)
? client.getChildren().usingWatcher(this).forPath(path) // 重新发起连接,并传入最新的子节点列表
: Collections.<String>emptyList()); //
}
}
}
@Override
public void delete(String path) {
try {
client.delete().forPath(path);
} catch (NoNodeException e) {
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
@Override
public List<String> getChildren(String path) {
try {
return client.getChildren().forPath(path);
} catch (NoNodeException e) {
return null;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
CuratorZookeeperTransporter,实现 ZookeeperTransporter 接口,CuratorZookeeper 工厂实现类:
public class CuratorZookeeperTransporter implements ZookeeperTransporter {
public ZookeeperClient connect(URL url) {
return new CuratorZookeeperClient(url);
}
}