当前位置:文档之家› Zookeeper 预研分册

Zookeeper 预研分册

1.概述

1.1简介

Zookeeper分布式框架,是Google的Chubby一个开源的实现,是Apache Hadoop 的一个子项目,提供了协调分布式应用的基本服务,简化了分布式应用协调及其管理的难度,提供的功能包括统一命名服务、状态同步服务、集群管理等。

Zookeeper serer端基于java开发,client端提供c和java的api接口。包含一个简单的原语集,是Hadoop和Hbase的重要组件(HBase内置有Zookeeper,也可以使用外部Zookeeper),提供了分布式锁、队列、选举的接口,分布式锁和队列有Java和C两个版本,选举只有Java版本。

Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储,但是Zookeeper 并不是用来专门存储数据的,它的作用主要是用来维护和监控你存储的数据的状态变化。通过监控这些数据状态的变化,从而可以达到基于数据的集群管理。Zookeeper 主要是用来维护和监控一个目录节点树中存储的数据的状态,所有我们能够操作Zookeeper 的也和操作目录节点树大体一样,如创建一个目录节点,给某个目录节点设置数据,获取某个目录节点的所有子目录节点,给某个目录节点设置权限和监控这个目录节点的状态变化。

Zookeeper可以单机模式安装运行,长处在于通过分布式集群(一个leader,多个follower)实现分布式应用的可靠性。

组成Zookeeper的各个服务器必须要能相互通信。他们在内存中保存了服务器状态,也保存了操作的日志,并且持久化快照。只要大多数的服务器是可用的,那么Zookeeper 就是可用的。

1.2技术定位

Zookeeper可在集权管理,监控,分布式锁等多个场景使用,在开源软件HBase、Solr、Storm、Neo4j等中使用,在Yahoo、Rackspace、Linkedin、Twitter、Taobao、Ctrip 等公司被使用。

设计目的:

●最终一致性。client无论连接到哪个server,展示给它的都是同一个视图。

●可靠性。具有简单、健壮、良好的性能。

●实时性。Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或

者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。

●原子性。更新只能成功,或者失败,没有中间状态。

●顺序性。包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b

前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b 在消息a后被同一个发送者发布,a必将排在b前面。

缺点:

小数据处理、不支持大事务(数据操作保证原子性)。

1.3部署架构

在整个集群中只有一个leader,其他都是follower。如果leader出现问题,系统会采用leader election算法重新选举一个leader,因此,各节点之间要能保证相互连接,每个节点都要配置集群中其他节点的信息。

所有的Sever都保存一份完整数据,所有的Server都能对外服务(包括leader)。客户端随机连接到集群中的一个Server,并且维持TCP连接。并且发送请求,获取回复和事件,并且发送连接信号。如果这个TCP连接断掉了,那么客户端可以连接另外一个服务器。

Client与Servr之间采用长连接,连接建立后,Server产生session ID(64位)返回给Client。如果Client与Server通信足够频繁,不需要额外维护session。否则,Client 每T/3发一次心跳包给Server,如果Client T2/3没收到来自Server的心跳回应,就会切换到新的Server上,T为用户设置的session超时时间(zookeeper_init参数

recv_timeout)。因为Zookeeper集群会将Client的session信息持久化,在session没有超时之前,Client与Server的连接可以在各个Server之间透明的切换。

Zookeeper读写模式:

Replicated Database是包含了所有数据的内存数据库。

可以从任何一个Server读,当有读请求时,处理该请求的Server直接读取本地副本数据返回给Client端,无需转发给leader。

改变Zookeeper服务状态的请求和写请求按照协同协议执行,更新操作都是串行执行的。Server转发所有写请求给leader,然后leader通过原子广播协议(Zookeeper Atomic Broadcast)将请求广播给所有follower,leader收到一半以上的写成功ACK后,就认为写成功了,就会将该写进行持久化,并告诉客户端写成功。

Zookeeper存在WAL(write-ahead-log,预写日志),对于每一个更新操作,先写WAL,再更新内存数据,然后通知Client结果。另外,Zookeeper会定期将内存中的目录树进行Snapshot存到磁盘,一方面数据持久化,另一方面可以加快重启后的恢复速度,比通过执行全部WAL恢复速度快。

FIFO:

对于每一个ZooKeeper客户端而言,所有的操作都是遵循FIFO顺序的,这一特性是由下面两个基本特性来保证的:

●ZooKeeper Client与Server之间的网络通信是基于TCP,TCP保证了Client/Server

之间传输包的顺序。

●ZooKeeper Server执行客户端请求也是严格按照FIFO顺序的。

1.4数据模型

数据结构。Zookeeper名字空间由znode组成,组织方式与文件系统极为相似,其中各个节点相当于目录和文件,通过路径作为唯一标识,与文件系统不同的是,每个节点除了数据,还可以有子节点,除了EPHEMERAL类型的节点不允许有子节点。

节点信息。znode存储协调数据,例如状态、配置、位置等信息,每个节点存储的数据量很小、可配置。每个节点由一个Stat结构(数据变化版本号、ACL变化、时间戳),以允许缓存验证与协调更新。每当节点数据改变时,数据变化版本号递增。节点具有一个访问控制列表ACL约束哪些人能执行哪些操作。节点不支持重命名。

数据版本。节点数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本。

读写原子性。节点数据以原子方式读写,读操作读取全部内容,写操作替换全部内容。

节点监视。znode可以被监视,包括节点数据的修改,以及子节点的变化等,一旦变化server通知设置监视的客户端,通过该特性可以实现配置集中管理、集群管理、分布式锁等功能。

EPHEMERAL节点。znode可以是临时节点,一旦创建这个znode的客户端与服务器失去联系,session失效,znode将自动删除。

SEQUENCE节点。znode的目录名可以自动编号,如App1已经存在,再创建的话,将会自动命名为App2 。

结构如下图所示:

每个节点由3部分组成:

●stat,状态信息,描述该znode的版本、权限等信息。

●data,与该znode关联的数据。

●children,该znode下的子节点。

1.5软件安装

1、下载安装包:https://www.doczj.com/doc/b73524924.html,/apache/Zookeeper/Zookeeper-3.3.6/

2、tar zxvf Zookeeper-3.3.6.tar.gz

1.5.1单机模式

1、进入Zookeeper目录下的conf子目录,创建zoo.cfg,配置说明参见伪集群模式章节:

tickTime=2000

dataDir=/home/market/Desktop/code/Zookeeper/data3

dataLogDir=/home/market/Desktop/code/Zookeeper/logs3

clientPort=2183

2、启动server。

./bin/zkServer.sh start #连接zoo.cfg

3、启动client。

./bin/zkClient.sh -server localhost:2183

1.5.2伪集群模式

所谓伪集群,是指在单台机器上启动多个Zookeeper进程,组成一个集群,以启动3个Zookeeper进程为例,将Zookeeper目录另外拷贝2份。

|--Zookeeper0

|--Zookeeper1

|--Zookeeper2

1、更改Zookeeper0/conf/zoo.cfg为:

ckTime=2000

initLimit=5

syncLimit=2

dataDir=/home/market/code/Zookeeper/data0

dataLogDir=/home/market/code/Zookeeper/logs0

clientPort=2180

maxClientCnxns=60

server.0=127.0.0.1:8880:7770

server.1=127.0.0.1:8881:7771

server.2=127.0.0.1:8882:7772

●ckTime:毫秒值,Zookeeper的基本时间单位。

●initLimit:集群中包含多台server, 其中一台为leader, 其余的为follower。initLimit

参数配置初始化连接时,follower和leader之间最长能忍受的心跳时间间隔数,如果超过10s(5倍ckTime)leader还没有收到follower的返回信息,就表明这个follower 连接失败。

●syncLimit:leader和follower之间发送消息、请求和应答的最大时间长度。

●dataDir:保存数据的目录,可以是任意目录。

●dataLogDir:log目录,可以是任意目录,如果没有设置该参数,使用和dataDir相

同的设置。

●clientPort:client连接服务器的端口,服务器监听该端口,接受客户端的请求。

●maxClientCnxns:最大客户端连接数。

●server.X=A:B:C 其中X是一个数字,表示这是第几号server,A是该server的IP地

址。B配置该server和集群中的leader交换消息的端口。C配置选举leader时所使用的端口。由于配置的是伪集群模式,所以各个server的B, C参数必须不同。

2、参照Zookeeper0/conf/zoo.cfg,修改Zookeeper1、Zookeeper2的zoo.cfg,只需修改dataDir、dataLogDir、clientPort参数即可。

3、在dataDir中新建myid文件,写入一个数字,该数字表示是第几号server,该数字必须和zoo.cfg文件中的server.X中的X一一对应。

/home/market/code/Zookeeper/data0/myid文件中写入0,

/home/market/code/Zookeeper/data1/myid文件中写入1,

/home/market/code/Zookeeper/data02/myid文件中写入2。

4、分别进入Zookeeper0/bin,Zookeeper1/bin,Zookeeper2/bin三个目录,启动server。

5、任意选择一个server目录,启动客户端连接到其中一个server,bin/zkCli.sh -server localhost:2181,在当前目录下生成zookeeper.out日志文件。

1.5.3集群模式

1、集群模式的配置和伪集群基本一致,由于集群模式下,各server部署在不同的机器上,因此各server的conf/zoo.cfg可以完全一样,例如:

ckTime=2000

initLimit=5

syncLimit=2

dataDir=/home/market/code/Zookeeper/data0

dataLogDir=/home/market/code/Zookeeper/logs0

clientPort=2180

server.43=10.1.39.43:8880:7770

server.47=10.1.39.47:8880:7770

server.49=10.1.39.49:8880:7770

2、需要注意的是各server的dataDir目录下的myid文件中的数字必须不同。10.1.39.43 server的myid为43,10.1.39.47 server的myid为47,10.1.39.49 server的myid为49。

1.5.4C client

Zookeeper C client的实现在src/c目录下,进入到该目录安装Zookeeper C client,步骤如下,3.4.6版本make出错,3.3.6版本没有问题:

(1)./configure

(2)make

(3)make install

(4)

cp include/proto.h /usr/local/include/c-client-src/

cp src/zk_adaptor.h /usr/local/include/c-client-src/.

cp src/zk_hashtable.h /usr/local/include/c-client-src/.

头文件位置:/usr/local/include/c-client-src/

库文件位置:/usr/local/lib/

1.6参考资料

1、AboutYun论坛

https://www.doczj.com/doc/b73524924.html,/forum-149-1.html

2、IBM文章介绍

https://www.doczj.com/doc/b73524924.html,/developerworks/cn/opensource/os-cn-Zookeeper/

3、使用和场景介绍:Zookeeper在携程的使用和场景介绍

https://www.doczj.com/doc/b73524924.html,/slides/8986

4、C API指南

https://www.doczj.com/doc/b73524924.html,/haippy/archive/2013/02/21/2920280.html

5、原理介绍

https://www.doczj.com/doc/b73524924.html,/blog/2014486

6、HBase应用

https://www.doczj.com/doc/b73524924.html,/blog/899632

https://www.doczj.com/doc/b73524924.html,/javaman_chen/article/details/7200405

7、开发常见问题

https://www.doczj.com/doc/b73524924.html,/?p=1189

8、zookeeper编程笔记

https://www.doczj.com/doc/b73524924.html,/caosiyang/archive/2012/11/09/2763190.html

https://www.doczj.com/doc/b73524924.html,/?p=2438

https://www.doczj.com/doc/b73524924.html,/2014/03/zookeeper-in-offline-computing.html 2.指令操作

2.1server操作

2.1.1启停server

若配置为伪集群模式,在不同的zookeeper/bin/目录下启动zkServer.sh,意味着对不同的server(zookeeper/conf/zoo.cfg中配置)进行操作:

1、启动服务器

$ bin/zkServer.sh start

2、检查服务器状态

$ bin/zkServer.sh status

JMX enabled by default

Using config: /home/market/code/soft/Zookeeper3/bin/../conf/zoo.cfg

Mode: standalone

3、停止服务器

$ bin/zkServer.sh stop

4、重启服务器

$ bin/zkServer.sh restart

2.1.2连接server

Zookeeper命令行工具类似于Linux的shell环境,使用它可以简单的对Zookeeper进行访问、创建、修改等操作。伪集群模式下,不同zookeeper/bin/zkCli.sh的使用没有区别。$ bin/zkCli.sh -server localhost:2180

2.1.3server切换

connect host:port:

[zk: localhost:2180(CONNECTED) 1] connect localhost:2181

2015-02-11 05:58:26,840 - INFO [main:Zookeeper@544] - Session:

0x4b78d21ff90002 closed

2015-02-11 05:58:26,840 - INFO

[main-EventThread:ClientCnxn$EventThread@516] - EventThread shut down

2.1.4退出客户端

退出客户端:

[zk: localhost:2180(CONNECTED) 4] quit

关闭当前会话连接,但不退出客户端:

[zk: localhost:2180(CONNECTED) 95] close

2015-02-17 22:11:30,941 - INFO [main:ZooKeeper@544] - Session:

0x4b97b2002b0017 closed

2015-02-17 22:11:30,941 - INFO

[main-EventThread:ClientCnxn$EventThread@516] - EventThread shut down

2.2指令说明

2.2.1指令一览

帮助命令help:

[zk: localhost:2183(CONNECTED) 21] help

Zookeeper -server host:port cmd args

get path [watch]

ls path [watch]

ls2 path [watch]

stat path [watch]

create [-s] [-e] path data acl

delete path [version]

quit

close

connect host:port

set path data [version]

history

redo cmdnum

setAcl path acl

getAcl path

printwatches on|off

delquota [-n|-b] path

listquota path

setquota -n|-b val path

sync path

addauth scheme auth

指令与C API对应关系参见《Zookeeper C API》。

2.2.2创建znode节点

创建节点/hello,并将字符串“world”关联到该节点中,如果没有指定value会创建失败:[zk: localhost:2183(CONNECTED) 4] create /hello world

Created /hello

[zk: localhost:2183(CONNECTED) 5] ls /

[hello, Zookeeper]

3种节点类型:

●persistent节点不和特定的session绑定,不会随着创建该节点的session结束而消失,

而是一直存在,除非该节点被显式删除。

●ephemeral节点是临时性的,如果创建该节点的session结束,该节点就会自动被删

除。ephemeral节点不能拥有子节点。虽然ephemeral节点与创建它的session绑定,但只要该节点没有被删除,其他session就可以读写该节点中关联的数据。使用-e参数指定创建ephemeral节点。

create -e /ephemeral ephe

●sequence节点,严格的说,并非节点类型中的一种。sequence节点既可以是

persistent的,也可以是ephemeral的。创建sequence节点时,server会在指定的节点名称后加上一个数字序列,该数字序列是递增的。因此可以多次创建相同的

sequence节点,而得到不同的节点。使用-s参数指定创建sequence节点。

[zk: localhost:2183(CONNECTED) 40] create /sequence seque

Created /sequence

[zk: localhost:2183(CONNECTED) 41] create -s /sequence/item item

Created /sequence/item0000000000

[zk: localhost:2183(CONNECTED) 42] create -s /sequence/item item

Created /sequence/item0000000001

[zk: localhost:2183(CONNECTED) 43] create -s /sequence/item item

Created /sequence/item0000000002

2.2.3删除znode节点

delete命令可以删除指定znode,当该znode拥有子znode时,必须先删除其所有子znode,否则操作将失败。

rmr命令可用于代替delete命令,rmr是一个递归删除命令,如果发生指定节点拥有子节点时,rmr命令会首先删除子节点。

[zk: localhost:2183(CONNECTED) 18] delete /hello

Node not empty: /hello

[zk: localhost:2183(CONNECTED) 19] rmr /hello

2.2.4设置znode数据

[zk: localhost:2180(CONNECTED) 7] set /hello newworld

2.2.5watch事件

2.2.5.1stat命令

stat命令获取节点的状态信息,第一个参数为znode,若第二个参数为true,则监听该znode的更新和删除事件。

2.2.5.2get命令

get命令返回指定节点的数据和状态信息。

[zk: localhost:2183(CONNECTED) 8] get /hello

zxid:

Zookeeper状态的每一次改变,都对应着一个递增的transaction id,该id称为zxid。由于zxid递增的性质,如果zxid1小于zxid2,那么zxid1肯定先于zxid2发生。创建、更新、删除任意节点的数据,都会导致Zookeeper状态发生改变,从而导致zxid的增加。

session:

在client和server通信之前,先要建立连接,该连接称为session。连接建立后,如果发生连接超时、授权失败或者显式关闭连接,连接便处于close状态,此时session结束。

监视器设置:

get命令第一个参数指定znode,若第二个参数为true,说明监听该znode更新和删除事件,子节点的增删事件不会触发。

[zk: localhost:2183(CONNECTED) 48] get /sequence true

[zk: localhost:2183(CONNECTED) 49] create -s /sequence/item item

Created /sequence/item0000000004

[zk: localhost:2183(CONNECTED) 50] delete /sequence/item0000000004

[zk: localhost:2183(CONNECTED) 51] rmr /sequence

WATCHER::

WatchedEvent state:SyncConnected type:NodeDeleted path:/sequence

2.2.5.3ls和ls2命令

包括ls和ls2,ls显示当前znode下的子节点,ls2显式当前znode下的子节点、以及当前znode的状态信息、不会显示当前znode的值。

[zk: localhost:2180(CONNECTED) 18] ls /

[hello, sequence, Zookeeper]

[zk: localhost:2180(CONNECTED) 19] ls2 /

[hello, sequence, Zookeeper]

cZxid = 0x0

ctime = Wed Dec 31 16:00:00 PST 1969

mZxid = 0x0

mtime = Wed Dec 31 16:00:00 PST 1969

pZxid = 0x100000005

cversion = 2

dataVersion = 0

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 0

numChildren = 3

设置监视器:

ls命令第一个参数指定znode,若第二个参数为true,说明监听该znode子节点的增删,以及该znode的删除事件,只是一次性触发。

[zk: localhost:2183(CONNECTED) 45] ls /sequence true

[item0000000001, item0000000002, item0000000000]

[zk: localhost:2183(CONNECTED) 46] create -s /sequence/item item WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/sequence Created /sequence/item0000000003

2.2.6查看历史命令

history查看历史命令,以下数字105为命令编号,"ls"为具体命令:

[zk: localhost:2180(CONNECTED) 115] history

105 - ls /

106 - get cn

107 - get /cn

108 - get /cn

2.2.7重做历史命令

109表示"get /cn"的命令编号,redo 109表示重新执行命令"get /cn":

2.2.8监视打印设置

on打开watch打印项,off则关闭:

[zk: localhost:2180(CONNECTED) 147] printwatches on|off

2.2.9设置JVM

Zookeeper进程存在,但是不接受新的请求,log报错如下:

需要配置Zookeeper的JVM,可以在./conf/下配置java.env:

#!/bin/bash

export JAVA_HOME=/usr/java/jdk1.6.0.17/

export JVMFLAGS="-Xms1024m -Xmx1024m $JVMFLAGS"

-Xms1024m是最小内存,-Xmx1024m是最大内存。

或者修改zkServer.sh:

3.开发指南

3.1 C API简介

Zookeeper C API大部分接口以zoo_开头,只有少量接口以zookeeper_开头。

除了zookeeper_init、zoo_multi、zoo_amulti批量操作相关的zoo_op_t初始化外,其他API的第一个参数均是zhandle_t *zh,即Zookeeper句柄的指针。

除了初始化、销毁、设置日志等级、辅助函数外,Zookeeper C API根据同步和异步特性分为两类,同步接口以zoo_*打头,异步接口zoo_a*打头。

同步API:

只有zookeeper_mt库提供,主线程调用API后,等待io线程完成对应操作后再返回。

异步API:

两个库都提供,但调用方式不同。

●zookeeper_mt主线程调用API后立即返回,不是等待异步API实际完成后再返回,

所以在异步API返回时并不能确定异步API执行是否成功,不能依据返回值判断是否执行成功,即使返回OK。在io线程准备好数据后,由completion线程执行回调函数,在回调函数中依据返回值rc判断执行是否成功。

如果会话已经建立,提交了异步API,即使在程序退出时异步API没有执行完成,在程序退出后异步API依然会执行。

如果会话没有建立,提交了异步API,假如在程序退出时会话依然没有建立,则异步API不会执行。

如果会话没有建立,提交了异步API,假如在程序退出时会话已经建立,则异步API会执行。

●zookeeper_st为单线程,提供了对应的事件处理函数:zookeeper_interest、

zookeeper_process,应用程序可以根据这两个API完成对应的事件循环,进行异步API处理。

同步API与异步API区别:

●同步API等待Server端执行完成后再返回,异步API不等待Server端实际完成就立

即返回,所以在同步API返回时可以判断执行是否成功,但是在异步API返回时无法得知是否执行成功。

●异步API比同步API多了异步回调函数,该函数不同于监视回调函数,在异步回调函

数中判断异步API是否执行成功。

●异步API、同步API执行时都可以设置监视回调函数,可以设置监视回调函数的API

包括exists、get、get_children。

异步API回调函数:

●在异步API中使用的回调函数,不是在异步API返回时立即调用,而是在异步API实

际执行完成后或者Zookeeper客户端失去连接时(zookeeper_close)被调用。

●如果异步API提交了操作,但是在Zookeeper客户端断开时,异步API仍然没有执行

完成,此时异步API回调函数会被调用,参数值并不是异步API实际执行的情况。所以在提交异步API后,要预留一段时间等待异步API完成时调用异步回调函数。

●pzk关闭时,以下三个异步API已提交到Server端,但是Server还没有返回执行情

况,此时异步回调函数被调用,参数rc为-116、zookeeper is closing,参数rc并不能反映异步API在Server端的实际执行情况。

char path[32] = "/xyz";

pthread_mutex_lock(&mutex);

zoo_acreate(pzk, path, "value", 5,

&ZOO_OPEN_ACL_UNSAFE, 0, string_completion, "acreate");

zoo_aexists(pzk, path, 1, stat_completion, "aexists");

zoo_adelete(pzk, path, -1, void_completion, "adelete");

zookeeper_close(pzk);

监视回调函数与异步回调函数调用顺序:

先执行完成引起监视事件的动作,再执行监视回调函数,最后执行异步API回调函数。

Zookeeper C API错误码:

中定义enum ZOO_ERRORS,详情参见《Zookeeper C API》。

3.2编译说明

1、通常需要包含头文件

2、Zookeeper C客户端分别提供了单线程的库与多线程的库:

●zookeeper_st只是为了用于不支持pthread或者支持不完善的系统环境,除此之

外,应使用mt库。zookeeper_st只提供异步操作的API,应用程序需要在自己的事件循环中,调用api进行相关操作。

●zookeeper_mt会启动两个独立线程:网络io线程和completion线程,封装了

内部的事件循环,分别提供了同步和异步的API,采用mt库编译时必须增加宏

-DTHREADED。

网络io线程:负责与服务端通信,包括发送业务层API调用请求、服务端响应数据、服务端watch事件数据。

completion线程:从completion_to_process队列中取出数据,执行异步回调、watch回调,单线程对所有事件按照顺序回调。

编译示例:

g++ -DTHREADED -I/usr/local/include/c-client-src/ -L/usr/local/lib/

-lzookeeper_mt cli.c

3.3初始化与销毁

3.3.1初始化句柄

创建客户端与服务器通信的句柄以及对应于此句柄的会话,会话创建是异步的过程,所

以zookeeper_init返回时,会话不一定建立。zookeeper_init返回非空句柄不代表初始化完成,只是代表句柄创建成功。仅当会话建立成功后,操作才会提交到Server端。

如果使用zookeeper_mt库,zookeeper_init调用成功,会启动io线程、completion 两个线程。

ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn,

int recv_timeout,

const clientid_t * clientid,

void *context, int flags);//失败返回NULL

●host为逗号隔开的IP:PORT对,每个IP:PORT对代表一个zookeeper server,例如

"127.0.0.1:2180,127.0.0.1:2181,127.0.0.1:2182"。host可以是Zookeeper集群中的全部或部分Zookeeper实例的IP:PORT对,Client随机连接其中一台Server。

●fn,全局的监视器回调函数,不允许设置为NULL。当zookeeper_init调用后会话建

立时或者发生事件通知时,该函数被调用,fn并不是由销毁句柄或者程序退出触发的。

●recv_timeout,单位毫秒,客户端连接服务器的超时时间。

如果超过recv_timeout客户端没有连接上Zookeeper,则表示连接超时。

另外,如果客户端断开连接recv_timeout,则session失效。

●clientid,客户端尝试重连的先前会话的ID,如果不需要重连先前的会话,则设置为0。

如果clientid对应的会话超时,或者由于某种原因clientid变为无效了,那么

zookeeper_init 将返回一个非法的zhandle_t,通过zhandle_t 的状态可以获知zookeeper_init 调用失败的原因。(通常为ZOO_EXPIRED_SESSION_STATE)。

●context,与zhandle_t 实例相关联的“上下文对象”(可以通过该参数为zhandle_t

传入自定义类型的数据),应用程序可以通过zoo_get_context 访问它(例如在监视器回调函数中),当然zookeeper 内部没有用到该参数,所以context 可以设置为NULL。

●flags,目前为保留参数,设置为0。

zhandle_t* zkhandle = zookeeper_init(host, zktest_watcher_g,

timeout, 0, (void *)"init", 0);

判断成功初始化(句柄创建成功+会话已建立)的3种方法,初始化成功后再使用Zookeeper:

●zoo_state(zkhandle),判断返回的state是否为ZOO_CONNECTED_STATE。

●在zookeeper_init中设置watcher,当zookeeper client与server会话建立后,触

发watcher,当watcher 的state = 3(ZOO_CONNECTED_STATE),type = -1(ZOO_SESSION_EVENT)时,确认会话成功建立,此时zookeeper client 初始化成功,可进行后续操作。

●尝试调用zoo_exists或zoo_get_data等操作,根据操作结果判断初始化是否成功。

zookeeper_init设置recv_timeout 100000ms,但客户端与服务端断开连接30s

就session失效了:

关于session超时时间的确定:zookeeper_init中设置的超时时间并非真正的session 超时时间,session超时时间需要server与client协商,业务通过

zoo_recv_timeout(zhandle_t* zh)获取server与client协商后的超时时间。服务端: minSessionTimeout (默认值为:tickTime * 2) , maxSessionTimeout(默认值

为:tickTime * 20), ticktime的默认值为2000ms。所以session范围为4s ~ 40s 。客户端:sessionTimeout,无默认值,创建实例时设置recv_timeout 值。经常会认为创建zookeeper客户端时设置了sessionTimeout为100s,而没有改变server端的配置,默认值是不会生效的。原因:客户端的zookeeper实例在创建连接时,将sessionTimeout 参数发送给了服务端,服务端会根据对应的minSession/maxSession Timeout的设置,强制修改sessionTimeout参数,也就是修改为4s~40s 返回的参数。所以服务端不一定会以客户端的sessionTImeout做为session expire管理的时间。

3.3.2销毁句柄

销毁句柄,释放资源:

●调用该函数后,会话将不可用。再对句柄进行操作,将产生不确定的结果。

●一个句柄只能调用一次,多次调用将产生不确定的结果。

●函数返回前,会将未发送完的请求发送完,所以可能会阻塞。

ZOOAPI int zookeeper_close(zhandle_t * zh);

3.4创建节点

3.4.1ACL说明

ACL权限说明:

●ACL指定所有用户的访问权限,权限不区分用户。

●节点的ACL没有继承关系,每个节点ACL独立控制。

●每个客户端连接都有一个id,客户端试图访问节点时,用id与ACL比对,以确定客户

端的访问权限。

struct Id 结构为:

struct Id {

char *scheme;

char *id;

};

struct ACL 结构为:

struct ACL {

int32_t perms;

struct Id id;

};

struct ACL_vector 结构为:

struct ACL_vector {

int32_t count;//data元素个数

struct ACL *data;

};

scheme:id:

●world: 它下面只有一个id叫anyone, world:anyone代表任何人,zookeeper中对

所有人有权限的节点就是属于world:anyone的。

●auth: 它不需要id, 只要是通过authentication的user都有权限(zookeeper支持

通过kerberos来进行authencation, 也支持username/password形式的

authentication)。

●digest: 它对应的id为username:BASE64(SHA1(password)),它需要先通过

username:password形式的authentication。

●ip: 它对应的id为客户机的IP地址,设置的时候可以设置一个ip段,比如

ip:192.168.1.0/16, 表示匹配前16个bit的IP段。

●super: 在这种scheme情况下,对应的id拥有超级权限,可以做任何事情(cdrwa)。

与ACL.perms(znode访问权限)相关的常量,中定义:

●const int ZOO_PERM_READ=1<<0;//允许客户端读取该节点的值以及子节点列表。

●const int ZOO_PERM_WRITE=1<<1;//允许客户端设置该节点的值。

●const int ZOO_PERM_CREATE=1<<2;//允许客户端在该节点下创建子节点。

●const int ZOO_PERM_DELETE=1<<3;//允许客户端删除该节点及子节点。

●const int ZOO_PERM_ADMIN=1<<4;//允许客户端执行set_acl,设置当前节点权限。

●const int ZOO_PERM_ALL=0x1f;//允许客户端执行所有操作,等价与上述所有标志的或。

与ACL.id相关的常量,中定义:

●struct Id ZOO_ANYONE_ID_UNSAFE=("world", "anyone");

●struct Id ZOO_AUTH_IDS=("auth", "");

三种标准的ACL_vector,中定义,通常使用第一个:

●struct ACL_vector ZOO_OPEN_ACL_UNSAFE;

//(ZOO_PERM_ALL,ZOO_ANYONE_ID_UNSAFE)

●struct ACL_vector ZOO_READ_ACL_UNSAFE;

//(ZOO_PERM_READ, ZOO_ANYONE_ID_UNSAFE)

相关主题
文本预览
相关文档 最新文档