zoukankan      html  css  js  c++  java
  • zk如何实现watch

    在客户端发送命令:stat /zhang watch

    在zk server中产生如下图的调用栈:

    //在DataTree类中有
    private final WatchManager dataWatches = new WatchManager();
    
    //在WatchManager类中有
    private final HashMap<String, HashSet<Watcher>> watchTable =
        new HashMap<String, HashSet<Watcher>>();
    
    private final HashMap<Watcher, HashSet<String>> watch2Paths =
        new HashMap<Watcher, HashSet<String>>();

    我们详细分析addWatch代码:

    //path就是客户端命令中的"/zhang",而Watcher就是客户端的连接对象NIOServerCnxn
    //可以理解为客户端就是一个Watcher
    //public abstract class ServerCnxn implements Stats, Watcher
    //public class NIOServerCnxn extends ServerCnxn
    public synchronized void addWatch(String path, Watcher watcher) {
        //多个客户端关注一个path
        HashSet<Watcher> list = watchTable.get(path);
        if (list == null) {
            // don't waste memory if there are few watches on a node
            // rehash when the 4th entry is added, doubling size thereafter
            // seems like a good compromise
            list = new HashSet<Watcher>(4);
            watchTable.put(path, list);
        }
        list.add(watcher);
    
        //一个客户端关注多个path
        HashSet<String> paths = watch2Paths.get(watcher);
        if (paths == null) {
            // cnxns typically have many watches, so use default cap here
            paths = new HashSet<String>();
            watch2Paths.put(watcher, paths);
        }
        paths.add(path);
    }

    在创建、删除、设置节点数据时,会触发watch:

    public Set<Watcher> triggerWatch(String path, EventType type, Set<Watcher> supress) {
        //生成事件
        WatchedEvent e = new WatchedEvent(type,    KeeperState.SyncConnected, path);
        HashSet<Watcher> watchers;
        synchronized (this) {
            //删除关注path的客户端
            watchers = watchTable.remove(path);
            if (watchers == null || watchers.isEmpty()) {
                if (LOG.isTraceEnabled()) {
                    ZooTrace.logTraceMessage(LOG,
                            ZooTrace.EVENT_DELIVERY_TRACE_MASK,
                            "No watchers for " + path);
                }
                return null;
            }
            for (Watcher w : watchers) {
                //删除该客户端关注的path
                HashSet<String> paths = watch2Paths.get(w);
                if (paths != null) {
                    paths.remove(path);
                }
            }
        }
        for (Watcher w : watchers) {
            if (supress != null && supress.contains(w)) {
                continue;
            }
            //每个客户端处理watch事件
            //NIOServerCnxn.process(WatchedEvent event)
            w.process(e);
        }
        return watchers;
    }
  • 相关阅读:
    在預設設定下,SQL Server 不允許遠端連接
    windows7语言包安装失败
    使一个销售组织能够销售另一个销售组织的产品
    转:多线程六种多线程方法解决UI线程阻塞
    转:BeginInvoke和EndInvoke方法 (原网址:http://www.cnblogs.com/nokiaguy/archive/2008/07/13/1241817.html)
    员工客户的统驭科目不能更改?
    公司间采购的退货(有序列号)
    排程 经典图示
    取消凭证分解 (取消公司下的多个利润中心)
    查找已删除的交货单信息
  • 原文地址:https://www.cnblogs.com/allenwas3/p/8081863.html
Copyright © 2011-2022 走看看