Zookeeper(五)Watcher机制

本文深入探讨了Zookeeper的Watcher机制,从Watcher的结构和参数传递开始,详细阐述了客户端如何向服务端发送数据,包括header部分和request请求内容。接着,分析了客户端接收服务端数据的过程,特别是数据变更通知和数据结果返回的处理,尤其是EventThread在处理服务端返回数据时的角色。

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<
普通文本型问题,直接回答: --- ZooKeeper 的 **Watcher(观察者)机制** 是一种分布式事件通知系统,允许客户端监听 ZooKeeper 中节点(znode)的状态变化,并在发生变化时收到一次性通知。 ### 工作原理: 1. **注册监听器(Watcher)** 客户端在读取某个 znode 信息时(如调用 `getData`、`getChildren` 或 `exists`),可以注册一个 `Watcher` 回调函数。例如: ```java zooKeeper.getData("/myNode", watcher, stat); ``` 2. **事件触发条件** 当被监听的 znode 发生以下变化之一时: - 节点数据修改(`NodeDataChanged`) - 节点被创建(`NodeCreated`) - 节点被删除(`NodeDeleted`) - 子节点变化(`NodeChildrenChanged`) ZooKeeper 服务端会异步向注册了 Watcher 的客户端发送一个事件通知。 3. **事件回调执行** 客户端接收到通知后,自动调用之前注册的 `process(WatchedEvent event)` 方法,开发者可在其中编写响应逻辑。 4. **一次性机制** Watcher 是**一次性触发**的:一旦被触发,该 Watcher 即失效。若要持续监听,必须在回调中重新注册。 5. **轻量级设计** Watcher 不携带具体数据变更内容,仅通知“发生了某类事件”,客户端需再次主动查询最新状态以获取详细信息。 --- ### 特点与注意事项: - ✅ **异步通知**:事件通过异步方式推送给客户端,不影响主流程性能。 - ✅ **保证有序性**:ZooKeeper 保证同一客户端的事件按发送顺序处理。 - ❗ **不重复通知**:如果在收到事件前节点多次变更,只会通知一次最终状态。 - ❗ **先注册后事件**:只有在事件发生前注册的 Watcher 才能收到通知。 - ✅ 广泛用于实现:集群协调、配置中心动态刷新、分布式锁、Leader 选举等场景。 --- ### 总结: Watcher 机制ZooKeeper 实现**分布式协同感知**的核心功能,其本质是“**一次性的、轻量级的、事件驱动的状态监听**”。它使得多个分布式节点能够对共享状态的变化做出快速响应,是构建高可用分布式系统的重要基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值