1、配置开发环境
构建ZooKeeper本地库的最简单的方式是使用ant构建工具。在你解压缩的ZooKeeper发行包的目录中,有一个名为build.xml的文件,该文件包含了ant构建所需的构建步骤。你还需要用到automake、autoconf和cppunit这些工具,如果你使用Linux操作系统,需要确保这些工具在你的主机中可用。
一旦安装了所有必需的工具,你可以采用以下方式构建ZooKeeper的库:
ant compile-native
当构建完成,你可以在build/c/build/usr/lib中发现链接库文件,在build/c/build/usr/include/zookeeper发现你所需要的头文件。
2、开始会话
与ZooKeeper进行任何操作之前,我们首先需要一个zhandle_t句柄。我们通过调用zookeeper_init函数来获取句柄,函数定义如下:ZOOAPI zhandle_t* zookeeper_init(const char* host, //包含ZooKeeper服务集群的主机地址的字符串,地址格式为host:port,每组地址以逗号分隔。
watcher_fn fn, //用于处理事件的监视点函数
int recv_timeout, //会话过期时间,以毫秒为单位
const clientid_t* clientid,//之前已建立的一个会话的客户端ID,用于客户端重新连接
void* context,//返回的zkhandle_t句柄所使用的上下文对象
int flags);//该参数暂时没有使用,因此设置为0即可
zookeeper_init调用也许在实际完成会话建立前返回,因此只有当收到ZOO_CONNECTED_STATE事件时才可以认为会话建立完成。该事件可以通过监视点函数的实现来处理,该函数的定义如下:
typedef void (* watcher_fn)(zhandle_t* zh, //观察点函数引用的ZooKeeper句柄。
int type, //事件类型:ZOO_CREATED_EVENT、ZOO_DELETED_EVENT、ZOO_CHANGED_EVENT、ZOO_CHILD_EVENT、ZOO_SESSION_EVENT。
int state, //连接状态
const char* path,//被观察并触发事件的znode节点路径,如果事件为会话事件,路径为null
void* watcherCtx);//观察点的上下文对象
以下为一个监视点函数的实现示例:
static int connected = 0;
static int expired = 0;
void main_watcher(zhandle_t* zkh,
int type,
int state,
const char* path,
void* context) {
if (type == ZOO_SESSION_EVENT) {
if (state == ZOO_CONNECTED_STATE) {
connected = 1;//在接收到ZOO_CONNECTED_STATE事件后设置状态为已连接状态
} else if (state == ZOO_NOTCONNECTED_STATE) {
connected = 0;
} else if (state == ZOO_EXPIRED_SESSION_STATE) {
expired = 1;//在接收到ZOO_EXPIRED_SESSION_STATE事件后设置为过期状态(并关闭会话句柄)
connected = 0;
zookeeper_close(zkh);
}
}
}
将所有操作串在一起,我们的主节点的init函数如下所示:
static int server_id;
int init(char* hostPort) {
srand(time(NULL));
server_id = rand();//设置服务器ID
zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);//设置log日志的输出级别
zh = zookeeper_init(hostPort, //创建会话的调用
main_watcher,
15000,
0,
0,
0);
return errno;
}
代码前两行设置了生成随机数的种子以及主节点的标识符,我们使用server_id来标识不同的主节点.之后我们设置了日志消息的输出级别。
最后,我们调用了zookeeper_init函数进行初始化
3、引导主节点
引导(Bootstraping)主节点是指创建主从模式例子中使用的一些znode节点并竞选主要主节点的过程。我们首先创建四个必需的znode节点:
void bootstrap() {
if (!connected) {//如果尚未连接,记录日志并退出。
LOG_WARN(("Client not connected to ZooKeeper"));
return;
}
create_parent("/workers", "");//创建四个父节点:/workers、/assign、/tasks、/status
create_parent("/assign", "");
create_parent("/tasks", "");
create_parent("/status", "");
...
}
以下为create_parent函数:
void create_parent(const char* path,
c