Apache ZooKeeper 是一个分布式的,开放源码的,面向分布式应用程序的高性能协调服务器。是Google的Chubby一个开源的实现,它是一个为分布式应用提供一致性服务的软件,提供的功能包括:统一命名服务、分布式共享锁、配置管理、队列管理、集群管理等。Zookeeper 作为 Hadoop 项目中的一个子项目,是 Hadoop 集群管理的一个必不可少的模块,它主要用来控制集群中的数据,如它管理Hadoop 集群中的 NameNode,还有 Hbase 中 Master Election、Server 之间状态同步等。
· 统一命名服务(Name Service):分布式应用中,通常需要有一套完整的命名规则,既能够产生唯一的名称又便于人识别和记住,通常情况下用树形的名称结构是一个理想的选择,树形的名称结构是一个有层次的目录结构,既对人友好又不会重复。说到这里你可能想到了 JNDI,没错 Zookeeper 的Name Service 与 JNDI 能够完成的功能是差不多的,它们都是将有层次的目录结构关联到一定资源上,但是 Zookeeper 的 Name Service 更加是广泛意义上的关联,也许你并不需要将名称关联到特定资源上,你可能只需要一个不会重复名称,就像数据库中产生一个唯一的数字主键一样。Name Service 已经是 Zookeeper 内置的功能,你只要调用 Zookeeper 的 API 就能实现。如调用 create 接口就可以很容易创建一个目录节点。
· 分布式共享锁(Locks): 共享锁在同一个进程中很容易实现,但是在跨进程或者在不同 Server 之间就不好实现了。Zookeeper 却很容易实现这个功能,实现方式也是需要获得锁的 Server 创建一个 EPHEMERAL_SEQUENTIAL 目录节点,然后调用 getChildren方法获取当前的目录节点列表中最小的目录节点是不是就是自己创建的目录节点,如果正是自己创建的,那么它就获得了这个锁,如果不是那么它就调用exists(String path, boolean watch) 方法并监控Zookeeper 上目录节点列表的变化,一直到自己创建的节点是列表中最小编号的目录节点,从而获得锁,释放锁很简单,只要删除前面它自己所创建的目录节点就行了。
· 配置管理(Configuration Management):配置的管理在分布式应用环境中很常见,例如同一个应用系统需要多台 PC Server 运行,但是它们运行的应用系统的某些配置项是相同的,如果要修改这些相同的配置项,那么就必须同时修改每台运行这个应用系统的 PC Server,这样非常麻烦而且容易出错。像这样的配置信息完全可以交给Zookeeper 来管理,将配置信息保存在 Zookeeper 的某个目录节点中,然后将所有需要修改的应用机器监控配置信息的状态,一旦配置信息发生变化,每台应用机器就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中。
· 队列管理:Zookeeper 可以处理两种类型的队列:1、当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达,这种是同步队列。2、队列按照 FIFO 方式进行入队和出队操作,例如实现生产者和消费者模型。
· 集群管理(Group Membership):Zookeeper能够很容易的实现集群管理的功能,如有多台 Server 组成一个服务集群,那么必须要一个“总管”知道当前集群中每台机器的服务状态,一旦有机器不能提供服务,集群中其它集群必须知道,从而做出调整重新分配服务策略。同样当增加集群的服务能力时,就会增加一台或多台 Server,同样也必须让“总管”知道。Zookeeper 不仅能够帮你维护当前的集群中机器的服务状态,而且能够帮你选出一个“总管”,让这个总管来管理集群,这就是 Zookeeper 的另一个功能 Leader Election。
ZooKeeper 虽然是一个针对分布式系统的协调服务,但它本身也是一个分布式应用程序。它遵循一个简单的客户端-服务器模型,其中客户端 是使用服务的节点(即机器),而服务器 是提供服务的节点。ZooKeeper服务器的集合形成了一个 ZooKeeper 集合体(ensemble)。在任何给定的时间内,一个 ZooKeeper 客户端可连接到一个 ZooKeeper 服务器。每个 ZooKeeper 服务器都可以同时处理大量客户端连接。每个客户端定期发送 ping 到它所连接的 ZooKeeper 服务器,让服务器知道它处于活动和连接状态。被询问的ZooKeeper 服务器通过 ping 确认进行响应,表示服务器也处于活动状态。如果客户端在指定时间内没有收到服务器的确认,那么客户端会连接到集合体中的另一台服务器,而且客户端会话会被透明地转移到新的 ZooKeeper 服务器。
Zookeeper中的角色主要有以下三类
1.最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。
2 .可靠性:具有简单、健壮、良好的性能,如果消息m被到一台服务器接受,那么它将被所有的服务器接受。
3 .实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。
4 .等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。
5.原子性:更新只能成功或者失败,没有中间状态。
6 .顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。
Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。
每个Server在工作过程中有三种状态:
LOOKING:当前Server不知道leader是谁,正在搜寻
LEADING:当前Server即为选举出来的leader
FOLLOWING:leader已经选举出来,当前Server与之同步
当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。先介绍basic paxos流程:
1 .选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server
2 .选举线程首先向所有Server发起一次询问(包括自己);
3 .选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;
4. 收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;
5. 线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数, 设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1.每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。
选主的具体流程图如下所示:
选完leader以后,zk就进入状态同步过程。
1. leader等待server连接;
2 .Follower连接leader,将最大的zxid发送给leader;
3 .Leader根据follower的zxid确定同步点;
4 .完成同步后通知follower 已经成为uptodate状态;
5 .Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。
流程图如下所示:
Leader主要有三个功能:
1 .恢复数据;
2 .维持与Learner的心跳,接收Learner请求并判断Learner的请求消息类型;
3 .Learner的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不同的消息类型,进行不同的处理。
PING消息是指Learner的心跳信息;REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;ACK消息是Follower的对提议的回复,超过半数的Follower通过,则commit该提议;REVALIDATE消息是用来延长SESSION有效时间。
Leader的工作流程简图如下所示,在实际实现中,流程要比下图复杂得多,启动了三个线程来实现功能。
Follower主要有四个功能:
1. 向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);
2 .接收Leader消息并进行处理;
3 .接收Client的请求,如果为写请求,发送给Leader进行投票;
4 .返回Client结果。
Follower的消息循环处理如下几种来自Leader的消息:
1.PING消息:心跳消息;
2.PROPOSAL消息:Leader发起的提案,要求Follower投票;
3.COMMIT消息:服务器端最新一次提案的信息;
4.UPTODATE消息:表明同步完成;
5.REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息;
6.SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。
Follower的工作流程简图如下所示,在实际实现中,Follower是通过5个线程来实现功能的。
对于observer的流程不再叙述,observer流程和Follower的唯一不同的地方就是observer不会参加leader发起的投票。
ZooKeeper有一个类似于文件系统的数据模型,由znodes组成。可以将 znodes(ZooKeeper 数据节点)视为类似 UNIX 的传统系统中的文件,但它们可以有子节点。另一种方式是将它们视为目录,它们可以有与其相关的数据。每个这些目录都被称为一个znode。
(1)每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识,如/SERVER2节点的标识就为/APP3/SERVER2
(2)Znode可以有子znode,并且znode里可以存数据,但是EPHEMERAL类型的节点不能有子节点
(3)Znode中的数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本。
(4)znode 可以是临时节点,一旦创建这个znode的客户端与服务器失去联系,这个znode也将自动删除,Zookeeper 的客户端和服务器通信采用长连接方式,每个客户端和服务器通过心跳来保持连接,这个连接状态称为session,如果znode 是临时节点,这个session失效,znode也就删除了
(5)znode 的目录名可以自动编号,如 App1 已经存在,再创建的话,将会自动命名为App2
(6)znode可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的集中管理,集群管理,分布式锁等等。
示例:(以zookeeper-3.4.6.tar.gz为例)
1、下载安装文件
wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz
2、解压缩
tar xzvf zookeeper3.4.6.tar.gz
3、mv zookeeper3.4.6 zookeeper(非必须)
4、cd zkserver
5、mkdir data
6、mkdir logs
7、cd conf
8、vi zoo.cfg 设置如下参数
tickTime=2000
dataDir=/home/xiongyw/zookeeper/data
dataLogDir=/home/xiongyw/zookeeper/logs
clientPort=2181
参数说明:
tickTime: zookeeper中使用的基本时间单位, 毫秒值.
dataDir: 数据目录. 可以是任意目录.
dataLogDir: log目录, 同样可以是任意目录. 如果没有设置该参数, 将使用和dataDir相同的设置.
clientPort: 监听client连接的端口号.
至此, zookeeper的单机模式已经配置好了. 启动server只需运行脚本
bin/zkServer.sh start
Server启动之后, 就可以启动client连接server了, 执行脚本:
bin/zkCli.sh -server localhost:2181
所谓伪集群, 是指在单台机器中启动多个zookeeper进程, 并组成一个集群. 以启动3个zookeeper进程为例.
将zookeeper的目录拷贝2份:
|--zkserver1
|--zkserver2
|--zkserver3
更改zkserver1/conf/zoo.cfg文件为:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/xiongyw/zkcluster/zkserver1/data
dataLogDir=/home/xiongyw/zkcluster/zkserver1/logs
clientPort=2181
server.1=localhost:2287:3387
server.2=localhost:2288:3388
server.3=localhost:2289:3389
更改zkserver2/conf/zoo.cfg文件为:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/xiongyw/zkcluster/zkserver2/data
dataLogDir=/home/xiongyw/zkcluster/zkserver2/logs
clientPort=2182
server.1=localhost:2287:3387
server.2=localhost:2288:3388
server.3=localhost:2289:3389
更改zkserver3/conf/zoo.cfg文件为:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/xiongyw/zkcluster/zkserver2/data
dataLogDir=/home/xiongyw/zkcluster/zkserver2/logs
clientPort=2183
server.1=localhost:2287:3387
server.2=localhost:2288:3388
server.3=localhost:2289:3389
新增了几个参数, 其含义如下:
initLimit: zookeeper集群中的包含多台server, 其中一台为leader, 集群中其余的server为follower. initLimit参数配置初始化连接时, follower和leader之间的最长心跳时间. 此时该参数设置为5, 说明时间限制为5倍tickTime, 即5*2000=10000ms=10s.
syncLimit: 该参数配置leader和follower之间发送消息, 请求和应答的最大时间长度. 此时该参数设置为2, 说明时间限制为2倍tickTime, 即4000ms.
server.X=A:B:C 其中X是一个数字, 表示这是第几号server. A是该server所在的IP地址. B配置该server和集群中的leader交换消息所使用的端口. C配置选举leader时所使用的端口. 由于配置的是伪集群模式, 所以各个server的B, C参数必须不同.
在之前设置的dataDir中新建myid文件, 写入一个数字, 该数字表示这是第几号server. 该数字必须和zoo.cfg文件中的server.X中的X一一对应.
/home/xiongyw/zkcluster/zkserver1/data/myid文件中写入1, /home/xiongyw/zkcluster/zkserver2/data/myid文件中写入2, /home/xiongyw/zkcluster/zkserver3/data/myid文件中写入3.
分别进入
/home/xiongyw/zkcluster/zkserver1/bin,
/home/xiongyw/zkcluster/zkserver2/bin,
/home/xiongyw/zkcluster/zkserver3/bin三个目录, 启动server.
任意选择一个server目录, 启动客户端:
bin/zkCli.sh -server localhost:2181
集群模式的配置和伪集群基本一致.由于集群模式下, 各server部署在不同的机器上, 因此各server的conf/zoo.cfg文件可以完全一样.
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/home/zookeeper/data
dataLogDir=/home/zookeeper/logs
clientPort=2181
server.1=192.168.192.132:2888:3888
server.2=192.168.192.133:2888:3888
server.3=192.168.192.134:2888:3888
或者:
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/home/zookeeper/data
dataLogDir=/home/zookeeper/logs
clientPort=2181
server.1=Master:2888:3888
server.2=Slave1:2888:3888
server.3=Slave2:2888:3888
三台主机:/etc/hosts文件如下:
192.168.198.132 Master
192.168.198.133 Slave1
192.168.198.134 Slave2
[root@hadoop bin]# ./zkServer.sh status
JMX enabled by default
Using config: /usr/local/zk/bin/../conf/zoo.cfg
Error contacting service. It is probably not running.
网上问题答案有许多种,一一归纳:
1. zoo.cfg配置文件中指定目录却没有创建! 创建相应目录即可。
2. zoo.cfg中dataDir指定路径为Myid文件的路径。
Myid内容与:server.?=localhost:2888:3888 中你所设置?一致!
3.使用service iptables stop 关闭防火墙
使用service iptables status确认
4. 1,打开zkServer.sh 找到status)
STAT=`echo stat | nc localhost $(grep clientPort "$ZOOCFG" | sed -e 's/.*=//') 2> /dev/null| grep Mode`
在nc与localhost之间加上 -q 1 (是数字1而不是字母l)
如果已存在则去掉
5.2181端口被占用! #我就是死在这的,死了很久很久。。
zkServer.sh stop #先停止zookeep
netstat -an | grep 2181 #查看端口是否占用,如果占用
clientPort = 2888 #随便找个没占用的端口号!
6. 时间不同步的问题:只能同步时间
7. 时间没问题,但是集群就是不能正常操作,发现通过zkcli链接某一些节点的时候,链接进去之后一直打印日志信息
解决方案:bin/zkCleanup.sh count 3
如果这样解决不了的话,建议,删除当前zk节点的data目录中的内容【除了myid文件,其余都删掉】
zkCli.sh -server 127.0.0.1:2181
[zk: localhost:2182(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
connect host:port
get path [watch]
ls path [watch]
set path data [version]
rmr path
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
命令行工具的一些简单操作如下:
1. 显示根目录下、文件: ls / 使用 ls 命令来查看当前 ZooKeeper 中所包含的内容
2. 显示根目录下、文件: ls2 / 查看当前节点数据并能看到更新次数等数据
3. 创建文件,并设置初始内容: create /zk "test" 创建一个新的 znode节点“ zk ”以及与它关联的字符串
4. 获取文件内容: get /zk 确认 znode 是否包含我们所创建的字符串
5. 修改文件内容: set /zk "zkbak" 对 zk 所关联的字符串进行设置
6. 删除文件: delete /zk 将刚才创建的 znode 删除
7. 退出客户端: quit
8. 帮助命令: help
在准备好相应的配置之后,可以直接通过zkServer.sh 这个脚本进行服务的相关操作
1. 启动ZK服务: sh bin/zkServer.sh start
2. 查看ZK服务状态: sh bin/zkServer.sh status
3. 停止ZK服务: sh bin/zkServer.sh stop
4. 重启ZK服务: sh bin/zkServer.sh restart
ZooKeeper 支持某些特定的四字命令字母与其的交互。它们大多是查询命令,用来获取 ZooKeeper 服务的当前状态及相关信息。用户在客户端可以通过telnet 或 nc 向 ZooKeeper 提交相应的命令
ZooKeeper 四字命令 |
功能描述 |
conf |
输出相关服务配置的详细信息。 |
cons |
列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。包括“接受 / 发送”的包数量、会话 id 、操作延迟、最后的操作执行等等信息。 |
dump |
列出未经处理的会话和临时节点 |
envi |
输出关于服务环境的详细信息(区别于 conf 命令) |
reqs |
列出未经处理的请求 |
Ruok |
测试服务是否处于正确状态。如果确实如此,那么服务返回“imok ”,否则不做任何相应。 |
stat |
输出关于性能和连接的客户端的列表。 |
wchs |
列出服务器 watch 的详细信息。 |
wchc |
通过 session 列出服务器 watch 的详细信息,它的输出是一个与watch 相关的会话的列表。 |
wchp |
通过路径列出服务器 watch 的详细信息。它输出一个与 session相关的路径。 |
实例:(机器上要安装netcat-0.7.1-1.i386.rpm服务)
1. 可以通过命令:echo stat|nc 127.0.0.1 2182来查看哪个节点被选择作为follower或者leader
2.使用echoruok|nc 127.0.0.1 2182测试是否启动了该Server,若回复imok表示已经启动。
3. echo dump| nc 127.0.0.1 2182 ,列出未经处理的会话和临时节点。
4. echo kill | nc 127.0.0.1 2182 ,关掉server
5. echo conf | nc 127.0.0.1 2182 ,输出相关服务配置的详细信息。
6. echo cons | nc 127.0.0.1 2183 ,列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。
Leader信息:
Follower信息:
10. echo wchc | nc 127.0.0.1 2183 ,通过 session 列出服务器 watch 的详细信息,它的输出是一个与 watch 相关的会话的列表。
11. echo wchp | nc 127.0.0.1 2183 ,通过路径列出服务器 watch 的详细信息。它输出一个与 session 相关的路径。
客户端要连接 Zookeeper 服务器可以通过创建org.apache.zookeeper. ZooKeeper 的一个实例对象,然后调用这个类提供的接口来和服务器交互。前面说了 ZooKeeper 主要是用来维护和监控一个目录节点树中存储的数据的状态,所有我们能够操作 ZooKeeper 的也和操作目录节点树大体一样,如创建一个目录节点,给某个目录节点设置数据,获取某个目录节点的所有子目录节点,给某个目录节点设置权限和监控这个目录节点的状态变化。
String create(String path, byte[] data, List CreateMode createMode) |
创建一个给定的目录节点 path, 并给它设置数据,CreateMode 标识有四种形式的目录节点,分别是 PERSISTENT:持久化目录节点,这个目录节点存储的数据不会丢失;PERSISTENT_SEQUENTIAL:顺序自动编号的目录节点,这种目录节点会根据当前已近存在的节点数自动加 1,然后返回给客户端已经成功创建的目录节点名;EPHEMERAL:临时目录节点,一旦创建这个节点的客户端与服务器端口也就是 session 超时,这种节点会被自动删除;EPHEMERAL_SEQUENTIAL:临时自动编号节点 |
Stat exists(String path, boolean watch) |
判断某个 path 是否存在,并设置是否监控这个目录节点,这里的 watcher 是在创建 ZooKeeper 实例时指定的 watcher,exists方法还有一个重载方法,可以指定特定的watcher |
Stat exists(String path,Watcher watcher) |
重载方法,这里给某个目录节点设置特定的 watcher,Watcher 在 ZooKeeper 是一个核心功能,Watcher 可以监控目录节点的数据变化以及子目录的变化,一旦这些状态发生变化,服务器就会通知所有设置在这个目录节点上的 Watcher,从而每个客户端都很快知道它所关注的目录节点的状态发生变化,而做出相应的反应 |
void delete(String path, int version) |
删除 path 对应的目录节点,version 为 -1 可以匹配任何版本,也就删除了这个目录节点所有数据 |
List boolean watch) |
获取指定 path 下的所有子目录节点,同样 getChildren方法也有一个重载方法可以设置特定的 watcher 监控子节点的状态 |
Stat setData(String path, byte[] data, int version) |
给 path 设置数据,可以指定这个数据的版本号,如果 version 为 -1 怎可以匹配任何版本 |
byte[] getData(String path, boolean watch, Stat stat) |
获取这个 path 对应的目录节点存储的数据,数据的版本等信息可以通过 stat 来指定,同时还可以设置是否监控这个目录节点数据的状态 |
voidaddAuthInfo(String scheme, byte[] auth) |
客户端将自己的授权信息提交给服务器,服务器将根据这个授权信息验证客户端的访问权限。 |
Stat setACL(String path,List int version) |
给某个目录节点重新设置访问权限,需要注意的是 Zookeeper 中的目录节点权限不具有传递性,父目录节点的权限不能传递给子目录节点。目录节点 ACL 由两部分组成:perms 和 id。 |
List |
获取某个目录节点的访问权限列表 |
// 创建一个与服务器的连接
ZooKeeper zk = new ZooKeeper("localhost:" + CLIENT_PORT,
ClientBase.CONNECTION_TIMEOUT, new Watcher() {
// 监控所有被触发的事件
public void process(WatchedEvent event) {
System.out.println("已经触发了" + event.getType() + "事件!");
}
});
// 创建一个目录节点
zk.create("/testRootPath", "testRootData".getBytes(), Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
/* 目录节点四种状态
PERSISTENT:持久
PERSISTENT_SEQUENTIAL:持久序列
EPHEMERAL:临时
EPHEMERAL_SEQUENTIAL:临时序列
*/
// 创建一个子目录节点
zk.create("/testRootPath/testChildPathOne", "testChildDataOne".getBytes(),
Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
System.out.println(new String(zk.getData("/testRootPath",false,null)));
// 取出子目录节点列表
System.out.println(zk.getChildren("/testRootPath",true));
// 修改子目录节点数据
zk.setData("/testRootPath/testChildPathOne","modifyChildDataOne".getBytes(),-1);
System.out.println("目录节点状态:["+zk.exists("/testRootPath",true)+"]");
// 创建另外一个子目录节点
zk.create("/testRootPath/testChildPathTwo", "testChildDataTwo".getBytes(),
Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
System.out.println(new String(zk.getData("/testRootPath/testChildPathTwo",true,null)));
// 删除子目录节点
zk.delete("/testRootPath/testChildPathTwo",-1);
zk.delete("/testRootPath/testChildPathOne",-1);
// 删除父目录节点
zk.delete("/testRootPath",-1);
// 关闭连接
zk.close();
实际应用中,Dubbo推荐使用Zookeeper作为服务的注册中心。除了Zookpeer外还有另外三种模式服务注册模式:(multicast、 redis、 simple)。本文只介绍以Zookpeer作为注册中心给Dubbo提供分布式服务的功能。
在spring配置文件中注入以下连接方式
单机连接:
集群连接:
或者:
在pom.xml文件中引入两个jar包
Zookeeper.3.4.6
org.apache.zookeeper
zookeeper
3.4.6
IprocessData.java代码:
package com.uaapi.dubbo.service;
public interface IProcessData {
public String hello(String name);
}
ProcessDataImpl.java代码:
package com.uaapi.dubbo.service.impl;
import com.uaapi.dubbo.service.IProcessData;
public class ProcessDataImpl implements IProcessData {
@Override
public String hello(String name) {
System.out.println(name);
return "hello : " + name;
}
}
App.java:启动发布服务
package com.uaapi.dubbo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author xiongyw
*
*/
public class App {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "applicationProvider.xml" });
context.start();
System.out.println("按任意键退出");
System.in.read();
}
}
applicationProvider.xml文件:单机连接示例
pom.xml文件
4.0.0
com.uaapi.dubbo
dubbo-provider
0.0.1-SNAPSHOT
jar
dubbo-provider
http://maven.apache.org
UTF-8
junit
junit
3.8.1
test
commons-logging
commons-logging
1.1.1
com.alibaba
dubbo
2.5.3
org.javassist
javassist
3.18.1-GA
log4j
log4j
1.2.15
com.sun.jdmk
jmxtools
com.sun.jmx
jmxri
jms
javax.jms
mail
javax.mail
org.springframework
spring
2.5.6.SEC03
org.slf4j
slf4j-api
1.7.6
org.slf4j
slf4j-log4j12
1.6.1
com.github.adyliu
zkclient
2.0
org.apache.zookeeper
zookeeper
3.4.6
com.101tec
zkclient
0.4
ConsumerThd.java:消费调用
package com.uaapi.dubbo.consumer;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.uaapi.dubbo.service.IProcessData;
public class ConsumerThd {
public void sayHello() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "applicationConsumer.xml" });
context.start();
IProcessData demoService = (IProcessData) context.getBean("demoService");
System.out.println(demoService.hello("world"));
}
}
APP.java Main方法服务消费
package com.uaapi.dubbo;
import com.uaapi.dubbo.consumer.ConsumerThd;
/**
* @author xiongyw
*
*/
public class App {
public static void main(String[] args) {
ConsumerThd thd = new ConsumerThd();
thd.sayHello();
}
}
pom.xml文件
4.0.0
com.uaapi.dubbo
dubbo-consumer
0.0.1-SNAPSHOT
jar
dubbo-consumer
http://maven.apache.org
UTF-8
junit
junit
3.8.1
test
commons-logging
commons-logging
1.1.1
com.alibaba
dubbo
2.5.3
org.javassist
javassist
3.18.1-GA
log4j
log4j
1.2.15
com.sun.jdmk
jmxtools
com.sun.jmx
jmxri
jms
javax.jms
mail
javax.mail
org.springframework
spring
2.5.6.SEC03
org.slf4j
slf4j-api
1.7.6
org.slf4j
slf4j-log4j12
1.6.1
com.github.adyliu
zkclient
2.0
org.apache.zookeeper
zookeeper
3.4.5
pom
com.uaapi.dubbo
dubbo-provider
0.0.1-SNAPSHOT
服务发布成功,在dubbo-admin中查看效果截图:
服务发布成功,在zkcli.sh登陆查看效果截图:
http://zookeeper.apache.org/ zookpeer官网
http://zookeeper.apache.org/doc/trunk/zookeeperStarted.html zookeeper使用指南
http://dubbo.io/Developer+Guide-zh.htm dubbo开发指南
http://blog.csdn.net/xhh198781/article/details/10949697 Paxos算法与Zookpeer分析