zookeeper的配置:点击打开链接
zookeeper的配置:点击打开链接
zookeeper的简单命令:点击打开链接
博主是分布式的小白,最近要开始接触dubbo有点慌,上午查阅了下资料,大致了解了下dubbo,具体概念性、理论性的博文以后供上,先来个实际操作。博主了解到dubbo常与zookeeper一起玩耍,所以要先实践zokeeper。
本篇博文主要是写个像我一样白的小白,过于细节还请高手勿喷,错误之处还请指出改正。
zookeeper是需要到官方下载的。
http://zookeeper.apache.org/ 官网下载,然后download,我反正是发现了.tar.gz,然后下下来就解压喽。
1、单机安装、配置:
安装非常简单,只要获取到 Zookeeper 的压缩包并解压到某个目录如:G:\ZooKeeperAll\ZooKeeper1\zookeeper-3.4.8下。
配置文件存放在/conf/目录下,将zoo_sample.cfd文件名称改为zoo.cfg(因为默认调用时zoo.cfg文件所以一定要改哟), 缺省的配置内容如下:
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
dataDir=G:\\ZooKeeperAll\\ZooKeeper1\\data //这是我修改后的
dataLogDir=G:\\ZooKeeperAll\\ZooKeeper1\\log //这是我修改后的
# the port at which the clients will connect
clientPort=2181
- tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
- dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
- clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
每个zk的instance,都需要设置独立的数据存储目录、日志存储目录,所以dataDir、dataLogDir这二个节点对应的目录,需要手动先创建好。
当这些配置项配置好后,你现在就可以启动 Zookeeper 了:进入/bin目录 zkServer.cmd
启动后要检查 Zookeeper 是否已经在服务,输入 jps 看下进程。
啦啦啦,我也不知道对不对,反正就先这样继续做下去试试呗^_^
2、集群安装、配置:
Zookeeper 的集群模式的安装和配置也不是很复杂,所要做的就是增加几个配置项。集群模式除了缺省的配置项还要在zoo.cfg文件末尾增加集群中的机器ip、端口等:
2.1创建每个目录下conf/zoo.cfg配置文件
G:\ZooKeeperAll\zookeeper1\conf\zoo.cfg 内容如下:
tickTime=2000 initLimit=10 syncLimit=5 dataDir=G:\\ZooKeeperAll\\ZooKeeper1\\data dataLogDir=G:\\ZooKeeperAll\\ZooKeeper1\\log clientPort=2181 server.1=localhost:2287:3387 server.2=localhost:2288:3388 server.3=localhost:2289:3389
G:\ZooKeeperAll\zookeeper2\conf\zoo.cfg 内容如下:
tickTime=2000 initLimit=10 syncLimit=5dataDir=G:\\ZooKeeperAll\\ZooKeeper2\\data dataLogDir=G:\\ZooKeeperAll\\ZooKeeper2\\logclientPort=2182server.1=localhost:2287:3387server.2=localhost:2288:3388server.3=localhost:2289:3389
G:\ZooKeeperAll\zookeeper3\conf\zoo.cfg 内容如下:
tickTime=2000 initLimit=10 syncLimit=5dataDir=G:\\ZooKeeperAll\\ZooKeeper3\\data dataLogDir=G:\\ZooKeeperAll\\ZooKeeper3\\logclientPort=2183server.1=localhost:2287:3387server.2=localhost:2288:3388server.3=localhost:2289:3389
注:因为是在一台机器上模拟集群,所以端口不能重复,这里用2181~2183,2287~2289,以及3387~3389相互错开。
- initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 10*2000=20 秒
- syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 5*2000=10 秒
- server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
- 除了修改 zoo.cfg 配置文件,集群模式下还要配置一个文件 myid,这个文件在 dataDir 目录下,这个文件里面就有一个数据就是 A 的值,Zookeeper 启动时会读取这个文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是那个 server。
G:\ZooKeeperAll\ZooKeeper1\data\myid 中的内容为1,对应server.1中的1
G:\ZooKeeperAll\ZooKeeper2\data\myid 中的内容为2,对应server.2中的2
G:\ZooKeeperAll\ZooKeeper3\data\myid 中的内容为3,对应server.3中的3
生产环境中,分布式集群部署的步骤与上面基本相同,只不过因为各zk server分布在不同的机器,上述配置文件中的localhost换成各服务器的真实Ip即可。分布在不同的机器后,不存在端口冲突问题,可以让每个服务器的zk均采用相同的端口,这样管理起来比较方便。
2.2启动验证
进入各个/bin目录 ,然后运行 zkServer.cmd
可以启动客户端测试下:
进入bin目录下:
zkCli -server localhost:2181
(注:如果是远程连接,把localhost换成指定的IP即可)
成功后,应该会进到提示符下,类似下面这样:
[zk: localhost:2181(CONNECTED) 0]
然后,就可以用一些基础命令,比如 ls ,create ,delete ,get 来测试了(关于这些命令,大家可以查看文档),特别提一个很有用的命令rmr 用来递归删除某个节点及其所有子节点。
建立节点 create /zk hello
获得节点 get /zk
设置节点 set /zk hello2
建立子节点 set /zk/subzk hello3
输出节点目录 ls /zk
删除节点 delete /zk等等
还有一部分可以看看这个博文:点击打开链接
数据模型
Zookeeper 会维护一个具有层次关系的数据结构,它非常类似于一个标准的文件系统,如图所示:
Zookeeper 这种数据结构有如下这些特点:
- 每个子目录项如 NameService 都被称作为 znode,这个 znode 是被它所在的路径唯一标识,如 Server1 这个 znode 的标识为 /NameService/Server1
- znode 可以有子节点目录,并且每个 znode 可以存储数据,注意 EPHEMERAL 类型的目录节点不能有子节点目录
- znode 是有版本的,每个 znode 中存储的数据可以有多个版本,也就是一个访问路径中可以存储多份数据
- znode 可以是临时节点,一旦创建这个 znode 的客户端与服务器失去联系,这个 znode 也将自动删除,Zookeeper 的客户端和服务器通信采用长连接方式,每个客户端和服务器通过心跳来保持连接,这个连接状态称为 session,如果 znode 是临时节点,这个 session 失效,znode 也就删除了
- znode 的目录名可以自动编号,如 App1 已经存在,再创建的话,将会自动命名为 App2
- znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个是 Zookeeper 的核心特性,Zookeeper 的很多功能都是基于这个特性实现的,后面在典型的应用场景中会有实例介绍
3、java与zk的连接示例:
3.1 maven项目的pom.xml中先添加以下依赖项
<!--zk--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.8</version> </dependency>
3.2 最基本的示例程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package
yjmyzz;
import
java.io.IOException;
import
org.apache.zookeeper.*;
import
org.apache.zookeeper.data.Stat;
public
class
ZooKeeperHello {
public
static
void
main(String[] args)
throws
IOException, InterruptedException, KeeperException {
ZooKeeper zk =
new
ZooKeeper(
"172.28.20.102:2181"
,
300000
,
new
DemoWatcher());
//连接zk server
String node =
"/app1"
;
Stat stat = zk.exists(node,
false
);
//检测/app1是否存在
if
(stat ==
null
) {
//创建节点
String createResult = zk.create(node,
"test"
.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(createResult);
}
//获取节点的值
byte
[] b = zk.getData(node,
false
, stat);
System.out.println(
new
String(b));
zk.close();
}
static
class
DemoWatcher
implements
Watcher {
@Override
public
void
process(WatchedEvent event) {
System.out.println(
"----------->"
);
System.out.println(
"path:"
+ event.getPath());
System.out.println(
"type:"
+ event.getType());
System.out.println(
"stat:"
+ event.getState());
System.out.println(
"<-----------"
);
}
}
}
|
3.3 与zk集群的连接
zk的优点之一,就是高可用性,上面的代码连接的是单台zk server,如果这台server挂了,自然代码就会出错,事实上zk的API考虑到了这一点,把连接代码改成下面这样:
ZooKeeper zk = new ZooKeeper("172.28.20.102:2181,172.28.20.102:2182,172.28.20.102:2183", 300000, new DemoWatcher());//连接zk server
即:IP1:port1,IP2:port2,IP3:port3... 用这种方式连接集群就行了,只要有超过半数的zk server还活着,应用一般就没问题。但是也有一种极罕见的情况,比如这行代码执行时,刚初始化完成,正准备连接ip1时,因为网络故障ip1对应的server挂了,仍然会报错(此时,zk还来不及选出新leader),这个问题详见:http://segmentfault.com/q/1010000002506725/a-1020000002507402,参考该文的做法,改成:
1 ZooKeeper zk = new ZooKeeper("172.28.20.102:2181,172.28.20.102:2182,172.28.20.102:2183", 300000, new DemoWatcher());//连接zk server 2 if (!zk.getState().equals(ZooKeeper.States.CONNECTED)) { 3 while (true) { 4 if (zk.getState().equals(ZooKeeper.States.CONNECTED)) { 5 break; 6 } 7 try { 8 TimeUnit.SECONDS.sleep(5); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 } 13 }
但是这样代码未免太冗长,建议用开源的zkClient,官方地址: https://github.com/sgroschupf/zkclient,使用方法很简单:
<!--zkclient--> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency>
pom.xml先加这一坨,然后这样用:
1 @Test 2 public void testZkClient() { 3 ZkClient zkClient = new ZkClient("172.28.20.102:2181,172.28.20.102:2182,172.28.20.102:2183"); 4 String node = "/app2"; 5 if (!zkClient.exists(node)) { 6 zkClient.createPersistent(node, "hello zk"); 7 } 8 System.out.println(zkClient.readData(node)); 9 }