一、zookeeper 的安装与配置:
1.zookeeper安装
下载:https://zookeeper.apache.org/ 建议下载zookeeper 3.4.6稳定版的, 3.5版本的在搭建集群时,会出现服务启动失败的错误。
安装: 解压 即可
安装C 语言 api:
进入./zookeeper/src/c目录
./configure
make
make install
2.集群配置
Zookeeper 的配置文件在 conf 目录下,这个目录下有 zoo_sample.cfg 和 log4j.properties,需要将 zoo_sample.cfg 改名为 zoo.cfg,因为 Zookeeper 在启动时会找这个文件作为默认配置文件。下面详细介绍一下,这个配置文件中各个配置项的意义。
tickTime=2000
dataDir= /home/zoo/data
clientPort=2181
- tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
- dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
- clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
当这些配置项配置好后,你现在就可以启动 Zookeeper 了,启动后要检查 Zookeeper 是否已经在服务,可以通过 netstat – ano 命令查看是否有你配置的 clientPort 端口号在监听服务。
集群模式
Zookeeper 不仅可以单机提供服务,同时也支持多机组成集群来提供服务。实际上 Zookeeper 还支持另外一种伪集群的方式,也就是可以在一台物理机上运行多个 Zookeeper 实例,下面将介绍集群模式的安装和配置。
Zookeeper 的集群模式的安装和配置也不是很复杂,所要做的就是增加几个配置项。集群模式除了上面的三个配置项还要增加下面几个配置项:
initLimit=5
syncLimit=2
server.1=192.168.211.1:2888:3888
server.2=192.168.211.2:2888:3888
- initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
- syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒
- server.myid=ip:port1:port2:其中 myid 是一个数字,表示这个是第几号服务器;ip是这个服务器的 ip 地址;port1表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;port2表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 ip 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
除了修改 zoo.cfg 配置文件,集群模式下还要配置一个文件 myid,这个文件在 dataDir 目录下,这个文件里面就有一个数据就是 A 的值,Zookeeper 启动时会读取这个文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是那个 server。
二、Zookeeper的使用:
1.服务端的启动:
进入/bin目录,使用./zkServer.sh start 启动zookeeper服务。 使用./zkServer.sh stop 停止服务。./zkServer.sh status 查看服务状态 (leader or follower).
2.客户端命令的使用:
进入/bin目录下,使用 ./zkCli.sh –server host:port 登陆服务,例如
./zkCli.sh -server 192.168.1.91:2181,键入任意字符出现以下help命令。
[zk: localhost:2181(CONNECTED) 1] help
ZooKeeper -server host:port cmd args
connect host:port
get
path [watch]
ls
path [watch]
set
path data [version]
delquota
[-n|-b] path
quit
printwatches on|off
create [-s] [-e] path data acl
stat
path [watch]
close
ls2
path [watch]
history
listquota path
setAcl path acl
getAcl path
sync
path
redo
cmdno
addauth scheme auth
delete path [version]
setquota -n|-b val path
- create [-s] [-e]
path data acl
其中”-s”表示创建一个顺序自动编号的节点,”-e”表示创建一个临时节点.默认为持久性节点
例如:创建一个持久性节点和临时节点
[zk: localhost:2181(CONNECTED) 7] create /test null
Created /test
[zk: localhost:2181(CONNECTED) 8] create -e /test0 null
Created /test0
当会话退出,临时节点将会自动删除,并且临时节点无子节点。
关于ACL的设置和使用在下一节单独介绍。
2.get path [watch]和set path data [version]
get是获取Znode的数据及相关属性,而set是修改此Znode的数据.
3.ls path [watch]
查看Znode的子节点
4.stat path [watch]
查看Znode的属性
5.delete path [version]
删除Znode,前提若有子节点,先删除其子节点
6.addauth scheme auth
认证授权,若某个节点需要认证后才能查看,就需要此命令,具体见下节。
3.ACL 的使用
传统的文件系统中,ACL分为两个维度,一个是属组,一个是权限,子目录/文件默认继承父目录的ACL。而在Zookeeper中,node的ACL是没有继承关系的,是独立控制的.
多集群共用zookeeper又涉及一个权限隔离的问题。zookeeper本身提供了ACL机制,表示为scheme:id:permissions,第一个字段表示采用哪一种机制,第二个id表示用户,permissions表示相关权限,如只读,读写,管理等。
scheme: scheme对应于采用哪种方案来进行权限管理,zookeeper实现了一个pluggable的ACL方案,可以通过扩展scheme,来扩展ACL的机制。zookeeper-3.4.4缺省支持下面几种scheme:
world: 它下面只有一个id, 叫anyone, world:anyone代表任何人,zookeeper中对所有人有权限的结点就是属于world:anyone的
auth: 它不需要id, 只要是通过authentication的user都有权限(zookeeper支持通过kerberos (http://www.cnblogs.com/jankie/archive/2011/08/22/2149285.html)来进行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)
另外,zookeeper-3.4.4的代码中还提供了对sasl的支持,不过缺省是没有开启的,需要配置才能启用,具体怎么配置在下文中介绍。
* sasl: sasl的对应的id,是一个通过sasl authentication用户的id,zookeeper-3.4.4中的sasl authentication是通过kerberos来实现的,也就是说用户只有通过了kerberos认证,才能访问它有权限的node.(关于sasl 参考:http://www.wxdl.cn/cloud/zookeeper-sasl.html)
id: id与scheme是紧密相关的,具体的情况在上面介绍scheme的过程都已介绍.
permission: zookeeper目前支持下面一些权限:
权限 |
描述 |
备注 |
CREATE |
有创建子节点的权限 |
|
READ |
有读取节点数据和子节点列表的权限 |
|
WRITE |
有修改节点数据的权限 |
无创建和删除子节点的权限 |
DELETE |
有删除子节点的权限 |
|
ADMIN |
有设置节点权限的权限 |
客户端示例:
- create [-s] [-e] path data acl
create /acl test world:anyone:rwd
Created /test
- create -s /test/test null digest:test:V28q/NynI4JI3Rk54h0r8O5kMug=:rwcda
Created /test/test0000000000
- getAcl /acl 查看路径的acl信息
- setAcl /test digest:test:V28q/NynI4JI3Rk54h0r8O5kMug=:r
- setAcl /test auth:username:password:crdwa
- addauth /<node-name> digest <username>:<password>
ACL的原理:
ZooKeeper 的权限管理通过Server、Client 两端协调完成:
(1) Server端
一个ZooKeeper 的节点存储两部分内容:数据和状态,状态中包含ACL 信息。创建一个znode 会产生一个ACL 列表,列表中每个ACL 包括:
① 权限perms
② 验证模式scheme
③ 具体内容expression:Ids
例如,当scheme="digest" 时, Ids 为用户名密码, 即"root :J0sTy9BCUKubtK1y8pkbL7qoxSw"。ZooKeeper 提供了如下几种验证模式:
① Digest: Client 端由用户名和密码验证,譬如user:pwd
② Host: Client 端由主机名验证,譬如localhost
③ Ip:Client 端由IP 地址验证,譬如172.2.0.0/24
④ World :固定用户为anyone,为所有Client 端开放权限
(2) 客户端
Client 通过调用addAuthInfo()(java, c为zoo_add_auth)函数设置当前会话的Author信息。Server 收到Client 发送的操作请求(除exists、getAcl 之外),需要进行ACL 验证:对该请求携带的Author 明文信息加密,并与目标节点的ACL 信息进行比较,如果匹配则具有相应的权限,否则请求被Server 拒绝。
三、zookeeper原理机制
1.文件系统
Zookeeper维护一个类似文件系统的数据结构:
每个子目录项如 NameService 都被称作为 znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。
有四种类型的znode:
1、PERSISTENT-持久化目录节点
客户端与zookeeper断开连接后,该节点依旧存在
2、 PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点
客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号
3、EPHEMERAL-临时目录节点
客户端与zookeeper断开连接后,该节点被删除
4、EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点
客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号
2.通知机制
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。
Zookeeper 的watch函数时一次性触发的,即一 个watch事件将会在数据发生变更时发送给客户端。例如,如果客户端执行操作getData(“/znode1″, true),而后 /znode1 发生变更或是删除了,客户端都会得到一个 /znode1 的watch事件。如果 /znode1 再次发生变更,则在客户端没有设置新的watch的情况下,是不会再给这个客户端发送watch事件的。
这就是说,一个事件会发送向客户端,但可能在在操作成功的返回值到达发起变动的客户端之前,这个事件还没有送达watch的客户端。Watch是异步发送 的。但ZooKeeper保证了一个顺序:一个客户端在收到watch事件之前,一定不会看到它设置过watch的值的变动。网络时延和其他因素可能会导 致不同的客户端看到watch和更新返回值的时间不同。但关键点是,每个客户端所看到的每件事都是有顺序的。
四、使用场景
1.配置同步:
- 搭建zookeeper集群,在集群服务器上创建永久节点如:Authorization
- 需要更新缓存的客户机器,连接至集群,并通过zookeeper watch机制对Authorization节点设置watch。
- 当数据库认证信息发生变化时,对 Authorization 节点数据进行更新,从而触发客户机的watch 函数,在watch函数中进行更新缓存的操作。
注意事项:
- watch 时一次性触发的,因此在watch函数触发后,需要重新注册,从而实现永久监听。
- 由于网络原因,或者更新操作过于频繁时,在客户机处理更新操作,没有注册新的watch间隙,数据库的认证信息发生变化时,这时会出现客户端缓存和数据库数据不一致的错误,因此,在watch函数结束后,通过再次获取Authorization的相关信息(程序中使用的是mzxid)与之前的进行比较,若不一致,需要再次进行更新缓存操作。
- zookeeper session 失效问题 http://blog.csdn.net/kobejayandy/article/details/26289273当客户端收到SESSIONEXPIRED状态信息后,由于之前设置的watch将失效,因此,进行了关闭之前的连接,重新开始连接,并设置watch函数的操作。
2.集群管理
使用zookeeper可以进行集群管理,主要针对两点
- 是否有机器的加入或退出
解决这个问题,可以在约定一个父目录,gropmember,然后再父目录下面,每个机器创建临时节点,并且监听父目录的子节点变化消息,一旦有机器退出集群,对应的子节点也将被删除,其它机器将受到通知。同样,当加入新的机器时,其它机器也将受到通知。
- Master的选举
Master的选举与上面的原理大致一致,所有机器创建临时子节点并按顺序编号,每次选择编号最小的子节点对应的机器作为master即可。
另外:
zookeeper
zoo_get(zhandle_t *zh, const char *path, int watch, char *buffer,
int* buffer_len, struct Stat *stat);
1.在传递参数时,buffer_len 的值是buffer缓冲的大小,当zoo_get成功返回后,buffer_len将被至为对应node节点数据的长度
2.如何确定buffer的大小? 可以设置一个大约值,然后当zoo_get 返回后,从stat结构体中获取node数据长度,与返回的buffer_len 进行比较,若是不相符,说明缓冲区小了,这时可以拿到正确的长度,再次get即可。
stat结构体:
struct Stat {
int64_t czxid;
int64_t mzxid;
int64_t ctime;
int64_t mtime;
int32_t version;
int32_t cversion;
int32_t aversion;
int64_t ephemeralOwner;
int32_t dataLength;
int32_t numChildren;
int64_t pzxid;
};