系统环境:
操作系统:Mac OS 10.9.4
JDK版本:java version "1.7.0_51"
Zookeep:zookeeper-3.3.6.tar.gz
1.单机模式
略.
2.伪集群模式
2.1 解压zookeeper-3.3.6.tar.gz文件,并放入到/Users/Minutch/Documents/Zookeeper下
mkdir /Users/Minutch/Documents/Zookeeper
cd /Users/Minutch/Documents/Zookeeper
拷贝zookeeper-3.3.6.tar.gz到/Users/Minutch/Documents/Zookeeper下
cp ~/Downloads/zookeeper-3.3.6.tar.gz /Users/Minutch/Documents/Zookeeper/
cd /Users/Minutch/Documents/Zookeeper/
tar -xvf zookeeper-3.3.6.tar.gz
解压完毕,我们在看下现在的目录结构
查看zookeeper的目录结构: ls -l zookeeper-3.3.6
为了能模拟伪集群,我们现在假设搭建三台服务器,所以我们拷贝三份zookeeper目录,放在/Users/Minutch/Document/Zookeeper/下,命名分别为zookeeper1,zookeeper2,zookeeper3,命令如下:
cp -rf zookeeper-3.3.6 zookeeper1
cp -rf zookeeper-3.3.6 zookeeper2
cp -rf zookeeper-3.3.6 zookeeper3
执行完毕之后,当前的目录结构:
到现在为止,我们已经完成了前期的准备工作,接下来,将开始zookeeper的配置工作
2.2 为了模拟伪集群模式,拷贝三份zookeeper文件(上图所示),分别放在三个文件夹里,如下图,路径:/Users/Minutch/Downloads/zookeeper
a.修改conf/zoo_cfg.properties文件的名称为zoo.cfg,zookeeper服务启动时默认会读取conf/zoo.properties文件,命令如下:
mv zookeeper1/conf/zoo_sample.cfg zookeeper1/conf/zoo.cfg
mv zookeeper2/conf/zoo_sample.cfg zookeeper2/conf/zoo.cfg
mv zookeeper3/conf/zoo_sample.cfg zookeeper3/conf/zoo.cfg
b.为了区分集群环境下的不同zookeeper,所以需要在每个zookeeper下创建一个myid,里面填写一个数字唯一标示zookeeper。
vi zookeeper1/myid myid里面填写1
vi zookeeper2/myid myid里面填写2
vi zookeeper3/myid myid里面填写3
c. 修改每个zookeeper配置文件zoo.properties,新增集群的实例
zookeeper1的zoo.cfg配置文件如下:
dataDir=/Users/Minutch/Documents/Zookeeper/zookeeper1
# the port at which the clients will connect
clientPort=2181
server.1 = 127.0.0.1:2888:3888
server.2 = 127.0.0.1:2889:3889
server.3 = 127.0.0.1:2890:3890
zookeeper2的zoo.cfg配置文件如下:
dataDir=/Users/Minutch/Documents/Zookeeper/zookeeper2
# the port at which the clients will connect
clientPort=2182
server.1 = 127.0.0.1:2888:3888
server.2 = 127.0.0.1:2889:3889
server.3 = 127.0.0.1:2890:3890
zookeeper3的zoo.cfg配置文件如下:
dataDir=/Users/Minutch/Documents/Zookeeper/zookeeper3
# the port at which the clients will connect
clientPort=2183
server.1 = 127.0.0.1:2888:3888
server.2 = 127.0.0.1:2889:3889
server.3 = 127.0.0.1:2890:3890
配置文件解释
tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。 dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。 clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。 initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 5个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒 syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒 server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
d. 启动zookeeper服务,命令如下
zookeeper1/bin/zkServer.sh start
zookeeper2/bin/zkServer.sh start
zookeeper3/bin/zkServer.sh start
执行后提示以下信息:
JMX enabled by default
Using config: zookeeper3/bin/../conf/zoo.cfg
-n Starting zookeeper ...
STARTED
e. 查看当前运行Java的服务 jps
f. 查看每个服务的状态,命令如下
zookeeper1/bin/zkServer.sh status
zookeeper2/bin/zkServer.sh status
zookeeper3/bin/zkServer.sh status
mode为follower为从服务器,mode为leader的为主服务器,执行后的截图如下:
2.3 使用Zookeeper的命令(使用一个客户端,连接zookeeper1)
因为每个zookeeper的项目里面自带了一个客户端的代码,为了没有歧义,我们使用zookeeper-3.3.6这个没有启动服务的zookeeper客户端,去连接zookeeper1的服务器,命令如下:
zookeeper-3.3.6/bin/zkCli.sh -server 127.0.0.1:2181
执行之后,出现如下打印信息:
a. 使用命令:help,查看所有客户端的命令
[zk: 127.0.0.1:2181(CONNECTED) 0] 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
|
b.使用命令:ls / (查看根目录下的配置,有一个zookeeper的项)
[zk: 127.0.0.1:2181(CONNECTED) 4]
ls
/
[zookeeper]
|
b.使用命令:create,创建一个节点 /node ,值为hello(查看根目录下的配置,有一个zookeeper的项)
create
/node
hello
Created
/node
|
c.使用命令:ls / (查看根目录下的配置)
ls
/
[node, zookeeper]
|
d.使用命令:get,查看 /node 的数据信息
get
/node
hello
cZxid = 0x100000002
ctime = Mon Nov 17 14:12:52 CST 2014
mZxid = 0x100000002
mtime = Mon Nov 17 14:12:52 CST 2014
pZxid = 0x100000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
|
e.使用命令:set 修改数据(把/node 的hello,改称helloWorld)
set
/node
helloWorld
cZxid = 0x100000002
ctime = Mon Nov 17 14:12:52 CST 2014
mZxid = 0x100000003
mtime = Mon Nov 17 14:17:02 CST 2014
pZxid = 0x100000002
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 10
|
f.再次查看/node的信息
get
/node
helloWorld
cZxid = 0x100000002
ctime = Mon Nov 17 14:12:52 CST 2014
mZxid = 0x100000003
mtime = Mon Nov 17 14:17:02 CST 2014
pZxid = 0x100000002
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 10
numChildren = 0
|
g.使用命令:ls /
ls
/
[node, zookeeper]
|
h.使用命令:delete,删除 /node
delete
/node
|
i:使用命令:ls /
ls
/
[zookeeper]
|
j.使用命令:quit,退出客户端
quit
Quitting...
2014-11-17 14:20:45,684 - INFO [main:ZooKeeper@544] - Session: 0x149bb28b00b0000 closed
|
2.4 使用Java模拟上述操作
创建一个Java类,引用zookeeper 的jar包(在zookeeper的contrib下)
package
com.minutch.zookeeper;
import
java.io.IOException;
import
org.apache.zookeeper.CreateMode;
import
org.apache.zookeeper.KeeperException;
import
org.apache.zookeeper.WatchedEvent;
import
org.apache.zookeeper.Watcher;
import
org.apache.zookeeper.ZooDefs.Ids;
import
org.apache.zookeeper.ZooKeeper;
public
class
ZookeeperClientDemo {
public
static
void
main(String[] args)
throws
IOException, KeeperException, InterruptedException {
// 创建一个与服务器的连接
ZooKeeper zk =
new
ZooKeeper(
"127.0.0.1:2181"
,
5000
,
new
Watcher(){
@Override
public
void
process(WatchedEvent event) {
System.out.println(
"Event:"
+ event.getType());
}
});
// 查看根节点
System.out.println(
"ls / ====>"
+ zk.getChildren(
"/"
,
true
));
//创建一个目录节点
if
(zk.exists(
"/node"
,
true
) ==
null
) {
zk.create(
"/node"
,
"hello"
.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(
"create /ndoe hello"
);
// 查看 /node 节点数据
System.out.println(
"get /node ====>"
+
new
String(zk.getData(
"/node"
,
false
,
null
)));
// 查看根节点
System.out.println(
"ls / ====>"
+ zk.getChildren(
"/"
,
true
));
}
//创建一个子目录节点
if
(zk.exists(
"/node/sub1"
,
true
) ==
null
) {
zk.create(
"/node/sub1"
,
"sub1"
.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(
"create /node/sub1 sub1"
);
//查看node节点
System.out.println(
"ls /node ====>"
+ zk.getChildren(
"/node"
,
true
));
}
//修改节点数据
if
(zk.exists(
"/node"
,
true
) !=
null
) {
zk.setData(
"/node"
,
"changed"
.getBytes(), -
1
);
//查看 /node 数据
System.out.println(
"get /node ====>"
+
new
String(zk.getData(
"/node"
,
false
,
null
)));
}
//删除节点
if
(zk.exists(
"/node/sub1"
,
true
) !=
null
) {
zk.delete(
"/node/sub1"
, -
1
);
//查看根节点
System.out.println(
"ls / ====>"
+ zk.getChildren(
"/"
,
true
));
}
zk.close();
}
}
|