0.Watcher结构和传参
先看看Watcher定义的结构:
public interface Watcher {
/**
* This interface defines the possible states an Event may represent
*/
public interface Event {
/**
* Enumeration of states the ZooKeeper may be at the event
*/
public enum KeeperState {
/** Unused, this state is never generated by the server */
@Deprecated
Unknown (-1),
/** The client is in the disconnected state - it is not connected
* to any server in the ensemble. */
Disconnected (0),
/** Unused, this state is never generated by the server */
@Deprecated
NoSyncConnected (1),
/** The client is in the connected state - it is connected
* to a server in the ensemble (one of the servers specified
* in the host connection parameter during ZooKeeper client
* creation). */
SyncConnected (3),
/**
* Auth failed state
*/
AuthFailed (4),
/**
* The client is connected to a read-only server, that is the
* server which is not currently connected to the majority.
* The only operations allowed after receiving this state is
* read operations.
* This state is generated for read-only clients only since
* read/write clients aren't allowed to connect to r/o servers.
*/
ConnectedReadOnly (5),
/**
* SaslAuthenticated: used to notify clients that they are SASL-authenticated,
* so that they can perform Zookeeper actions with their SASL-authorized permissions.
*/
SaslAuthenticated(6),
/** The serving cluster has expired this session. The ZooKeeper
* client connection (the session) is no longer valid. You must
* create a new client connection (instantiate a new ZooKeeper
* instance) if you with to access the ensemble. */
Expired (-112);
private final int intValue; // Integer representation of value
// for sending over wire
}
/**
* Enumeration of types of events that may occur on the ZooKeeper
*/
public enum EventType {
None (-1),
NodeCreated (1),
NodeDeleted (2),
NodeDataChanged (3),
NodeChildrenChanged (4);
private final int intValue; // Integer representation of value
// for sending over wire
}
}
abstract public void process(WatchedEvent event);
}
Watcher机制包含对事件(Event)和通知方法(process)的定义。
而事件Event包含通知状态(KeeperState)和事件类型(EventType)。
通知方法process的参数WatchedEvent event封装了通知状态(KeeperState)和事件类型(EventType)
public class WatchedEvent {
final private KeeperState keeperState;
final private EventType eventType;
private String path;
//省略其他代码
}
所以服务端通知客户端时,客户端能够知道数据变更通知的状态和类型。
当创建一个ZooKeeper对象时,可以通过向构造函数传Watcher对象,它会保存在org.apache.zookeeper.ZooKeeper.ZKWatchManager.defaultWatcher,即是下面源码的“1处”,也就是说客户端保存了Watcher对象。
public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly) throws IOException{
LOG.info("Initiating client connection, connectString=" + connectString
+ " sessionTimeout=" + sessionTimeout + " watcher=" + watcher);
//1处
watchManager.defaultWatcher = watcher;
//2处
ConnectStringParser connectStringParser = new ConnectStringParser(connectString);
HostProvider hostProvider = new StaticHostProvider(connectStringParser.getServerAddresses());
//3处
cnxn = new ClientCnxn(connectStringParser.getChrootPath(),
hostProvider, sessionTimeout, this, watchManager,
getClientCnxnSocket(), canBeReadOnly);
cnxn.start();
}
此外,还可以通过ZooKeeper的register(Watcher watcher)方法来设置默认Watcher。
Zookeeper除了可以通过构造函数来设置默认的Watcher,还可以通过以下方法来设置Watcher。
public byte[] getData(final String path, Watcher watcher, Stat stat);
public Stat exists(final String path, Watcher watcher);
public List<String> getChildren(final String path, Watcher watcher, Stat stat)
并分别存在dataWatches、existWatches和childWatches中,其中key是指path。
private static class ZKWatchManager implements ClientWatchManager {
private final Map<String, Set<Watcher>> dataWatches = new HashMap<String, Set<Watcher>>();
private final Map<String, Set<Watcher>> existWatches = new HashMap<String, Set<Watcher>>();
private final Map<String, Set<Watcher>> childWatches = new H