zoukankan      html  css  js  c++  java
  • zookeeper 回调和Watcher

      ZooKeeper客户端可以对指定节点设置指定Watcher,当服务器指定节点发生变化是,客户端会收到服务器的通知,然后客户端可以执行相应Watcher的代码。

      默认ZooKeeper内置了一个watcher,用于打印收到的服务器的通知。

    源码ZooKeeperMain.Watcher:

     1 protected void connectToZK(String newHost) throws InterruptedException, IOException {
     2         if (zk != null && zk.getState().isAlive()) {
     3             zk.close();
     4         }
     5         host = newHost;
     6         zk = new ZooKeeper(host,
     7                  Integer.parseInt(cl.getOption("timeout")),
     8                  new MyWatcher());
     9  }
    10 
    11 private class MyWatcher implements Watcher {
    12         public void process(WatchedEvent event) {
    13             if (getPrintWatches()) {
    14                 ZooKeeperMain.printMessage("WATCHER::");
    15                 ZooKeeperMain.printMessage(event.toString());
    16             }
    17         }
    18  }
    View Code

      在获取子节点、获取数据、获取状态可以设置Watcher,该Watcher会被存储到Packet包中,当Packet包收到响应时注册该Watcher,当收到服务器notification时,执行Watcher代码。

    源码ZooKeeper.getChildren:

     1 public List<String> getChildren(final String path, Watcher watcher)
     2         throws KeeperException, InterruptedException
     3     {
     4         //将watcher封装成childwatcher
     5         WatchRegistration wcb = null;
     6         if (watcher != null) {
     7             wcb = new ChildWatchRegistration(watcher, clientPath);
     8         }
     9 
    10         final String serverPath = prependChroot(path);
    11         RequestHeader h = new RequestHeader();
    12         h.setType(ZooDefs.OpCode.getChildren);
    13         GetChildrenRequest request = new GetChildrenRequest();
    14         request.setPath(serverPath);
    15         request.setWatch(watcher != null);
    16         GetChildrenResponse response = new GetChildrenResponse();
    17         ReplyHeader r = cnxn.submitRequest(h, request, response, wcb);
    18         if (r.getErr() != 0) {
    19             throw KeeperException.create(KeeperException.Code.get(r.getErr()),
    20                     clientPath);
    21         }
    22         return response.getChildren();
    23     }
    View Code

    源码ClientCnxn.submitRequest:

     1 public ReplyHeader submitRequest(RequestHeader h, Record request,
     2             Record response, WatchRegistration watchRegistration)
     3             throws InterruptedException {
     4         ReplyHeader r = new ReplyHeader();
     5 //watchRegistration被封装到Packet中
     6         Packet packet = queuePacket(h, r, request, response, null, null, null,
     7                     null, watchRegistration);
     8         synchronized (packet) {
     9             while (!packet.finished) {
    10                 packet.wait();
    11             }
    12         }
    13         return r;
    14     }
    View Code

    源码ClientCnxn.queuePacket:

     1 Packet queuePacket(RequestHeader h, ReplyHeader r, Record request,
     2             Record response, AsyncCallback cb, String clientPath,
     3             String serverPath, Object ctx, WatchRegistration watchRegistration)
     4     {
     5         Packet packet = null;
     6         synchronized (outgoingQueue) {
     7             if (h.getType() != OpCode.ping && h.getType() != OpCode.auth) {
     8                 h.setXid(getXid());
     9             }
    10 //watchRegistration被封装到Packet中
    11             packet = new Packet(h, r, request, response, null,
    12                     watchRegistration);
    13             packet.cb = cb;
    14             packet.ctx = ctx;
    15             packet.clientPath = clientPath;
    16             packet.serverPath = serverPath;
    17             if (!zooKeeper.state.isAlive() || closing) {
    18                 conLossPacket(packet);
    19             } else {
    20                 // If the client is asking to close the session then
    21                 // mark as closing
    22                 if (h.getType() == OpCode.closeSession) {
    23                     closing = true;
    24                 }
    25                 outgoingQueue.add(packet);
    26             }
    27         }
    28 
    29         sendThread.wakeup();
    30         return packet;
    31     }
    View Code

    当Packet包收到响应时注册该Watcher,源码ClientCnxn.finishPacket:

     1 private void finishPacket(Packet p) {
     2         if (p.watchRegistration != null) {
     3             p.watchRegistration.register(p.replyHeader.getErr());
     4         }
     5 
     6         if (p.cb == null) {
     7             synchronized (p) {
     8                 p.finished = true;
     9                 p.notifyAll();
    10             }
    11         } else {
    12             p.finished = true;
    13             eventThread.queuePacket(p);
    14         }
    15     }
    View Code

    当收到服务器notification时,执行Watcher代码,源码ClientCnxn.EventThread:

     1 private void processEvent(Object event) {
     2    if (event instanceof WatcherSetEventPair) {
     3 //执行watcher
     4                   WatcherSetEventPair pair = (WatcherSetEventPair) event;
     5                   for (Watcher watcher : pair.watchers) {
     6                       try {
     7                           watcher.process(pair.event);
     8                       } catch (Throwable t) {
     9                           LOG.error("Error while calling watcher ", t);
    10                       }
    11                   }
    12               }
    13 }
    View Code

          在删除节点、创建节点、获取子节点、设置数据、获取数据、获取权限、设置权限等异步操作时,可以设置CallBack回调函数,该回调对象会被存储到Packet包中,当Packet包收到响应时执行CallBack代码。

    源码ZooKeeper.getChildren:

     1 public void getChildren(final String path, Watcher watcher,
     2             ChildrenCallback cb, Object ctx)
     3     {
     4         final String clientPath = path;
     5         WatchRegistration wcb = null;
     6         if (watcher != null) {
     7             wcb = new ChildWatchRegistration(watcher, clientPath);
     8         }
     9 
    10         final String serverPath = prependChroot(clientPath);
    11 
    12         RequestHeader h = new RequestHeader();
    13         h.setType(ZooDefs.OpCode.getChildren);
    14         GetChildrenRequest request = new GetChildrenRequest();
    15         request.setPath(serverPath);
    16         request.setWatch(watcher != null);
    17         GetChildrenResponse response = new GetChildrenResponse();
    18         cnxn.queuePacket(h, new ReplyHeader(), request, response, cb,
    19                 clientPath, serverPath, ctx, wcb);
    20     }
    View Code

    源码ClientCnxn.queuePacket:

     1 Packet queuePacket(RequestHeader h, ReplyHeader r, Record request,
     2             Record response, AsyncCallback cb, String clientPath,
     3             String serverPath, Object ctx, WatchRegistration watchRegistration)
     4     {
     5         Packet packet = null;
     6         synchronized (outgoingQueue) {
     7             if (h.getType() != OpCode.ping && h.getType() != OpCode.auth) {
     8                 h.setXid(getXid());
     9             }
    10             packet = new Packet(h, r, request, response, null,
    11                     watchRegistration);
    12             packet.cb = cb;
    13             packet.ctx = ctx;
    14             packet.clientPath = clientPath;
    15             packet.serverPath = serverPath;
    16             if (!zooKeeper.state.isAlive() || closing) {
    17                 conLossPacket(packet);
    18             } else {
    19                 // If the client is asking to close the session then
    20                 // mark as closing
    21                 if (h.getType() == OpCode.closeSession) {
    22                     closing = true;
    23                 }
    24                 outgoingQueue.add(packet);
    25             }
    26         }
    27 
    28         sendThread.wakeup();
    29         return packet;
    30     }
    View Code

    源码ClientCnxn.EventThread:

     1 private void processEvent(Object event) {
     2           try {
     3                   Packet p = (Packet) event;
     4                   int rc = 0;
     5                   String clientPath = p.clientPath;
     6                   if (p.replyHeader.getErr() != 0) {
     7                       rc = p.replyHeader.getErr();
     8                   }
     9                   if (p.response instanceof ExistsResponse
    10                           || p.response instanceof SetDataResponse
    11                           || p.response instanceof SetACLResponse) {
    12                       StatCallback cb = (StatCallback) p.cb;
    13                       if (rc == 0) {
    14                           if (p.response instanceof ExistsResponse) {
    15                               cb.processResult(rc, clientPath, p.ctx,
    16                                       ((ExistsResponse) p.response)
    17                                               .getStat());
    18                           } else if (p.response instanceof SetDataResponse) {
    19                               cb.processResult(rc, clientPath, p.ctx,
    20                                       ((SetDataResponse) p.response)
    21                                               .getStat());
    22                           } else if (p.response instanceof SetACLResponse) {
    23                               cb.processResult(rc, clientPath, p.ctx,
    24                                       ((SetACLResponse) p.response)
    25                                               .getStat());
    26                           }
    27                       } else {
    28                           cb.processResult(rc, clientPath, p.ctx, null);
    29                       }
    30                   } else if (p.response instanceof GetDataResponse) {
    31                       DataCallback cb = (DataCallback) p.cb;
    32                       GetDataResponse rsp = (GetDataResponse) p.response;
    33                       if (rc == 0) {
    34                           cb.processResult(rc, clientPath, p.ctx, rsp
    35                                   .getData(), rsp.getStat());
    36                       } else {
    37                           cb.processResult(rc, clientPath, p.ctx, null,
    38                                   null);
    39                       }
    40                   } else if (p.response instanceof GetACLResponse) {
    41                       ACLCallback cb = (ACLCallback) p.cb;
    42                       GetACLResponse rsp = (GetACLResponse) p.response;
    43                       if (rc == 0) {
    44                           cb.processResult(rc, clientPath, p.ctx, rsp
    45                                   .getAcl(), rsp.getStat());
    46                       } else {
    47                           cb.processResult(rc, clientPath, p.ctx, null,
    48                                   null);
    49                       }
    50                   } else if (p.response instanceof GetChildrenResponse) {
    51                       ChildrenCallback cb = (ChildrenCallback) p.cb;
    52                       GetChildrenResponse rsp = (GetChildrenResponse) p.response;
    53                       if (rc == 0) {
    54                           cb.processResult(rc, clientPath, p.ctx, rsp
    55                                   .getChildren());
    56                       } else {
    57                           cb.processResult(rc, clientPath, p.ctx, null);
    58                       }
    59                   } else if (p.response instanceof GetChildren2Response) {
    60                       Children2Callback cb = (Children2Callback) p.cb;
    61                       GetChildren2Response rsp = (GetChildren2Response) p.response;
    62                       if (rc == 0) {
    63                           cb.processResult(rc, clientPath, p.ctx, rsp
    64                                   .getChildren(), rsp.getStat());
    65                       } else {
    66                           cb.processResult(rc, clientPath, p.ctx, null, null);
    67                       }
    68                   } else if (p.response instanceof CreateResponse) {
    69                       StringCallback cb = (StringCallback) p.cb;
    70                       CreateResponse rsp = (CreateResponse) p.response;
    71                       if (rc == 0) {
    72                           cb.processResult(rc, clientPath, p.ctx,
    73                                   (chrootPath == null
    74                                           ? rsp.getPath()
    75                                           : rsp.getPath()
    76                                     .substring(chrootPath.length())));
    77                       } else {
    78                           cb.processResult(rc, clientPath, p.ctx, null);
    79                       }
    80                   } else if (p.cb instanceof VoidCallback) {
    81                       VoidCallback cb = (VoidCallback) p.cb;
    82                       cb.processResult(rc, clientPath, p.ctx);
    83                   }
    84           } catch (Throwable t) {
    85               LOG.error("Caught unexpected throwable", t);
    86           }
    87        }
    88     }
    View Code
  • 相关阅读:
    scala02
    5.主从复制
    4.mysql锁机制
    3mysql查询截取分析
    2.2mysql 索引优化
    2.1mysql索引优化分析
    1.mysql 架构介绍命令,配置文件,架构,存储引擎,
    ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'
    Glide使用
    网络通信框架Retrofit2
  • 原文地址:https://www.cnblogs.com/zhangwanhua/p/8404519.html
Copyright © 2011-2022 走看看