Zookeeper(二)监视(Watches)及回调函数

建立连接

这个步骤很简单,直接参照源码使用即可:

/*
bool ZkClient::Connect(int timeout, ZooLogLevel log_level) {
    VLOG(LEV) << "Connecting " << address_;
    timeout_ = timeout;
    log_level_ = log_level;
    zoo_set_debug_level(log_level);
    if (!DoConnect(timeout)) return false;
    return true;
}
*/
ZkClient zk_client;
zk_client.Connect();

监视

Zookeeper 所有的读方法 GetData()Exists()GetChildren() 都可以设置监视(Watches),前两者监视传入的节点,后者监控传入节点的子节点。函数原型如下:

// watcher: if non-null, a watcher will be set at the server to notify
//          the client if the node changes.
// global_watch: if true, a global watch will be set.
//               When watcher is non-null, global_watch is ignored.
// struct NodeData {
//    std::string path;
//    std::string value;
//    Stat stat;
// };

bool GetData(const std::string& path,
             NodeData* node_data,
             EventWatcher* watcher = NULL,
             bool global_watch = false);

bool Exists(const std::string& path,
            EventWatcher* watcher = NULL,
            bool global_watch = false);

bool GetChildren(const std::string& path,
                 std::vector* children,
                 EventWatcher* watcher = NULL);

监视事件可以理解为一次性的触发器。当设置监视的节点或其数据发生改变时,该监视事件会被发送到客户端。由于网络或其他因素可能导致不同的客户端感知到某一监视事件存在延迟,但不同的客户端所看到的一切监视具有保序性

为了更好地阐述 Watch 所做的工作,假设 ZK 服务器上有如下结构(引号内是对应节点的 value):

/
- /root ""
- - /root/kafka ""
- - /root/redis ""
- - - /root/redis/1 "table1"
- - - /root/redis/2 "table2"
- /local ""
- - /local/test ""

Exists("/root/redis") 返回一个 bool 值,指示该节点是否存在。
GetChildren("/root/redis", vec)获取 /root/redis 节点的所有子节点,保存在 vec 中。
GetData("/root/redis", node_data) 获取 /root/redis/1 节点的值,保存在 node_data 结构体中。

在以上例子中,我们没有设置回调(Watch 为 null),节点信息的获取是一次性的,变更时不会通知客户端。这样没有发挥这个函数异步调用的特性。

Watch 的设置是通过回调函数的方式实现的,例如在 Zookp 类内定义 UpdateNode() 方法作为设置 Watch 监视变更的函数,HandleEvent() 方法作为监视到变更时的回调函数,这两个方法的实现应如:

void Zookp::HandleEvent() {
    std::cout << "the watch node is changed, update!" << std::endl;
    UpdateNode();    // recursive call, to ensure monitor the child node permanently
}
void Zookp::UpdateNode() {
    std::vector children;
    zk_->GetChildren(path, &children, base::NewOneTimeCallback(this, &Zookp::HandleEvent));
    // deal with node and data info here
    ...
}

你可能感兴趣的:(Zookeeper(二)监视(Watches)及回调函数)