Zookeeper系列文章目录
1、zookeeper3.7.1安装与验证
2、zookeeper基本操作及应用示例(shell、java api、应用场景示例)
3、zookeeper的选举----经验证符合事实,网上很多都是错误的
4、zookeeper的java三种客户端介绍-Curator(crud、事务操作、监听、分布式计数器、分布式锁)
5、zookeeper的java -Curator(服务注册与发现)
本文接上一篇zookeeper的部署与验证。具体链接:zookeeper的部署与验证
本文从三个方面介绍zookeeper的基本操作及简单的应用场景。
一、shell操作
(一)、连接zookeeper的客户端及查看相关的帮助
# 连接客户端,在集群中的任一台均可
cd /usr/local/bigdata/apache-zookeeper-3.7.1/bin
#默认端口2181,本示例使用的端口是2118
./zkCli.sh -server server2:2118
# 连接成功
[zk: server2:2118(CONNECTED) 0]
# 查看help命令
[zk: server2:2118(CONNECTED) 0] help
ZooKeeper -server host:port -client-configuration properties-file cmd args
addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path [-b batch size]
delquota [-n|-b|-N|-B] path
get [-s] [-w] path
getAcl [-s] path
getAllChildrenNumber path
getEphemerals path
history
listquota path
ls [-s] [-w] [-R] path
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b|-N|-B val path
stat [-w] path
sync path
version
whoami
- 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
- 35
- 36
- 37
- 38
(二)、基本操作
1、查看目录 ls命令
[zk: server2:2118(CONNECTED) 2] ls /
[zookeeper]
- 1
- 2
2、查看目录 ls -s 命令
[zk: server1:2118(CONNECTED) 1] ls -s /
[zookeeper]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
# cZxid Zookeeper为节点分配的Id
# cTime 节点创建时间
# mZxid 修改后的id
# mtime 修改时间
# pZxid 子节点id
# cversion 子节点的version
# dataVersion 当前节点数据的版本号
# aclVersion 权限Version
# dataLength 数据长度
# numChildren 子节点个数
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
3、创建目录(创建一个新的 znode )
[zk: server1:2118(CONNECTED) 2] create /zk testdata
Created /zk
- 1
- 2
4、获取数据get
[zk: server1:2118(CONNECTED) 3] get /zk
testdata
[zk: server1:2118(CONNECTED) 4] get -s /zk
testdata
cZxid = 0x100000003
ctime = Wed Jul 20 09:25:28 CST 2022
mZxid = 0x100000003
mtime = Wed Jul 20 09:25:28 CST 2022
pZxid = 0x100000003
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
5、监听节点zk
当指定的znode或znode的子数据更改时,监视器会显示通知。只能在 get 命令中设置watch。
# 1、在client1设置监听
[zk: server1:2118(CONNECTED) 5] get -w /zk
Dior
# 2、在client2修改数据
[zk: server2:2118(CONNECTED) 13] set /zk "LV"
# 3、设置完成后,切换到client1发现变化,如下:
[zk: server1:2118(CONNECTED) 6]
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/zk
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
6、设置数据set
[zk: server1:2118(CONNECTED) 7] set /zk "YSL"
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/zk
# 查看数据
[zk: server2:2118(CONNECTED) 6] get -s /zk
YSL
cZxid = 0x100000003
ctime = Wed Jul 20 09:25:28 CST 2022
mZxid = 0x100000005
mtime = Wed Jul 20 09:33:57 CST 2022
pZxid = 0x100000003
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
[zk: server1:2118(CONNECTED) 9] set /zk "Gucci"
[zk: server2:2118(CONNECTED) 7] get -s /zk
Gucci
cZxid = 0x100000003
ctime = Wed Jul 20 09:25:28 CST 2022
mZxid = 0x100000006
mtime = Wed Jul 20 09:35:04 CST 2022
pZxid = 0x100000003
cversion = 0
dataVersion = 3
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
- 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
- 35
- 36
- 37
7、检查状态stat
[zk: server2:2118(CONNECTED) 8] stat /zk
cZxid = 0x100000003
ctime = Wed Jul 20 09:25:28 CST 2022
mZxid = 0x100000006
mtime = Wed Jul 20 09:35:04 CST 2022
pZxid = 0x100000003
cversion = 0
dataVersion = 3
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
8、删除znode
[zk: server2:2118(CONNECTED) 10] delete /zk
[zk: server2:2118(CONNECTED) 11] ls /
[zookeeper]
- 1
- 2
- 3
9、四类节点
同一个目录下,顺序节点的顺序号是共用的。
临时节点不能再创建子节点。session链接断开就没了。
9.1、无序持久节点(默认的)
命令:create /path data
[zk: server1:2118(CONNECTED) 15] create /zk "Dior"
Created /zk
[zk: server1:2118(CONNECTED) 16] get /zk
Dior
- 1
- 2
- 3
- 4
- 5
9.2、有序持久节点
有序节点名称=有序节点路基+10位顺序号,-s:sequence,按照曾经创建的节点累计
命令:create -s /path data
[zk: server1:2118(CONNECTED) 23] create -s /seq "persistent,sequence"
Created /seq0000000004
[zk: server1:2118(CONNECTED) 24] get /seq0000000004
persistent,sequence
- 1
- 2
- 3
- 4
- 5
9.3、无序临时节点
临时节点在client端口连接之后关闭,-e: temp
命令:create -e /path data
[zk: server1:2118(CONNECTED) 25] create -e /temp "no-persistent,no-sequence"
Created /temp
[zk: server1:2118(CONNECTED) 26] get /temp
no-persistent,no-sequence
[zk: server1:2118(CONNECTED) 27] ls /
[seq0000000004, temp, zk, zk_s0000000003, zookeeper]
[zk: server1:2118(CONNECTED) 28] quit
再连接进来 ls /查看,temp目录已经被删除了
[zk: server3:2118(CONNECTED) 0] ls /
[seq0000000004, zk, zk_s0000000003, zookeeper]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
9.4、有序临时节点
命令:create -s -e path data
[zk: server3:2118(CONNECTED) 1] create -s -e /temp "no-persistent,order"
Created /temp0000000006
[zk: server3:2118(CONNECTED) 3] ls /
[seq0000000004, temp0000000006, zk, zk_s0000000003, zookeeper]
- 1
- 2
- 3
- 4
9.5、统一目录下顺序节点编号是共用的
[zk: server3:2118(CONNECTED) 6] create -s /zk/seq "testing"
Created /zk/seq0000000000
[zk: server3:2118(CONNECTED) 7] create -s -e /zk/temp "test"
Created /zk/temp0000000001
[zk: server3:2118(CONNECTED) 8] ls /zk
[seq0000000000, temp0000000001]
- 1
- 2
- 3
- 4
- 5
- 6
(三)、Zookeeper 四字命令
zookeeper 支持某些特定的四字命令与其交互,用户获取 zookeeper 服务的当前状态及相关信息,用户在客户端可以通过 telenet 或者 nc(netcat) 向 zookeeper 提交相应的命令。
1、安装nc
$ yum install nc # centos
# 或
$ sudo apt install netcat # ubuntu
- 1
- 2
- 3
2、配置zookeeper的配置文件
vim conf/zoo.cfg
# 配置文件中增加一行
4lw.commands.whitelist=*
# 需要重启zookeeper
- 1
- 2
- 3
- 4
- 5
3、stat 命令
stat 命令用于查看 zk 的状态信息
[alanchan@localhost bin]$ echo stat |nc server1 2118
Zookeeper version: 3.7.1-a2fb57c55f8e59cdd76c34b357ad5181df1258d5, built on 2022-05-07 06:45 UTC
Clients:
/192.168.10.42:51690[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0.0/0
Received: 3
Sent: 2
Connections: 1
Outstanding: 0
Zxid: 0x200000001
Mode: follower
Node count: 5
[alanchan@localhost bin]$ ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /usr/local/bigdata/apache-zookeeper-3.7.1/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[alanchan@localhost bin]$ echo stat |nc server2 2118
Zookeeper version: 3.7.1-a2fb57c55f8e59cdd76c34b357ad5181df1258d5, built on 2022-05-07 06:45 UTC
Clients:
/192.168.10.42:39400[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0.0/0
Received: 1
Sent: 0
Connections: 1
Outstanding: 0
Zxid: 0x200000001
Mode: follower
Node count: 5
[alanchan@localhost bin]$ echo stat |nc server3 2118
Zookeeper version: 3.7.1-a2fb57c55f8e59cdd76c34b357ad5181df1258d5, built on 2022-05-07 06:45 UTC
Clients:
/192.168.10.42:33050[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0.0/0
Received: 1
Sent: 0
Connections: 1
Outstanding: 0
Zxid: 0x200000001
Mode: follower
Node count: 5
- 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
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
4、ruok 命令
ruok 命令用于查看当前 zkserver 是否启动,若返回 imok 表示正常
[alanchan@localhost bin]$ echo ruok | nc server1 2118
imok
[alanchan@localhost bin]$ echo ruok | nc server2 2118
imok
[alanchan@localhost bin]$ echo ruok | nc server3 2118
imok
[alanchan@localhost bin]$
- 1
- 2
- 3
- 4
- 5
- 6
- 7
5、dump 命令
dump 命令用于列出未经处理的会话和临时节点
[alanchan@localhost bin]$ echo dump | nc server1 2118
SessionTracker dump:
Global Sessions(0):
ephemeral nodes dump:
Sessions with Ephemerals (0):
Connections dump:
Connections Sets (1)/(1):
1 expire at Wed Jul 20 11:39:03 CST 2022:
ip: /192.168.10.42:51712 sessionId: 0x0
[alanchan@localhost bin]$ echo dump | nc server2 2118
SessionTracker dump:
Session Sets (0)/(0):
ephemeral nodes dump:
Sessions with Ephemerals (0):
Connections dump:
Connections Sets (1)/(1):
1 expire at Wed Jul 20 11:38:40 CST 2022:
ip: /192.168.10.42:39416 sessionId: 0x0
[alanchan@localhost bin]$ echo dump | nc server3 2118
SessionTracker dump:
Global Sessions(0):
ephemeral nodes dump:
Sessions with Ephemerals (0):
Connections dump:
Connections Sets (1)/(1):
1 expire at Wed Jul 20 11:38:46 CST 2022:
ip: /192.168.10.42:33062 sessionId: 0x0
- 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
6、conf 命令
conf 命令用于查看服务器配置
[alanchan@localhost bin]$ echo conf | nc server1 2118
clientPort=2118
secureClientPort=-1
dataDir=/usr/local/bigdata/apache-zookeeper-3.7.1/data/version-2
dataDirSize=134218345
dataLogDir=/usr/local/bigdata/apache-zookeeper-3.7.1/data/version-2
dataLogSize=134218345
tickTime=2000
maxClientCnxns=60
minSessionTimeout=4000
maxSessionTimeout=40000
clientPortListenBacklog=-1
serverId=1
initLimit=10
syncLimit=5
electionAlg=3
electionPort=3888
quorumPort=2888
peerType=0
membership:
server.1=server1:2888:3888:participant
server.2=server2:2888:3888:participant
server.3=server3:2888:3888:participant
version=0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
7、cons 命令
cons 命令用于展示连接到服务器的客户端信息。
[alanchan@localhost bin]$ echo cons | nc server1 2118
/192.168.10.42:51722[0](queued=0,recved=1,sent=0)
[alanchan@localhost bin]$ echo cons | nc server2 2118
/192.168.10.42:39426[0](queued=0,recved=1,sent=0)
[alanchan@localhost bin]$ echo cons | nc server3 2118
/192.168.10.42:33072[0](queued=0,recved=1,sent=0)
[alanchan@localhost bin]$ ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/bigdata/apache-zookeeper-3.7.1/bin/../conf/zoo.cfg
Client port found: 2118. Client address: localhost. Client SSL: false.
Mode: leader
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
8、envi 命令
envi 命令用于查看环境变量。
[alanchan@localhost bin]$ echo envi | nc server1 2118
Environment:
zookeeper.version=3.7.1-a2fb57c55f8e59cdd76c34b357ad5181df1258d5, built on 2022-05-07 06:45 UTC
host.name=server.bl.com
java.version=1.8.0_144
java.vendor=Oracle Corporation
java.home=/usr/java/jdk1.8.0_144/jre
java.class.path=/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../zookeeper-server/target/classes:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../build/classes:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../zookeeper-server/target/lib/*.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../build/lib/*.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/zookeeper-prometheus-metrics-3.7.1.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/zookeeper-jute-3.7.1.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/zookeeper-3.7.1.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/snappy-java-1.1.7.7.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/slf4j-reload4j-1.7.35.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/slf4j-api-1.7.35.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/simpleclient_servlet-0.9.0.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/simpleclient_hotspot-0.9.0.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/simpleclient_common-0.9.0.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/simpleclient-0.9.0.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/reload4j-1.2.19.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/netty-transport-native-unix-common-4.1.76.Final.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/netty-transport-native-epoll-4.1.76.Final.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/netty-transport-classes-epoll-4.1.76.Final.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/netty-transport-4.1.76.Final.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/netty-resolver-4.1.76.Final.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/netty-handler-4.1.76.Final.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/netty-common-4.1.76.Final.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/netty-codec-4.1.76.Final.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/netty-buffer-4.1.76.Final.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/metrics-core-4.1.12.1.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jline-2.14.6.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jetty-util-ajax-9.4.43.v20210629.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jetty-util-9.4.43.v20210629.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jetty-servlet-9.4.43.v20210629.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jetty-server-9.4.43.v20210629.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jetty-security-9.4.43.v20210629.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jetty-io-9.4.43.v20210629.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jetty-http-9.4.43.v20210629.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/javax.servlet-api-3.1.0.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jackson-databind-2.13.2.1.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jackson-core-2.13.2.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/jackson-annotations-2.13.2.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/commons-cli-1.4.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../lib/audience-annotations-0.12.0.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../zookeeper-*.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../zookeeper-server/src/main/resources/lib/*.jar:/usr/local/bigdata/apache-zookeeper-3.7.1/bin/../conf:
java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.io.tmpdir=/tmp
java.compiler=<NA>
os.name=Linux
os.arch=amd64
os.version=2.6.32-696.el6.x86_64
user.name=root
user.home=/root
user.dir=/usr/local/bigdata/apache-zookeeper-3.7.1/bin
os.memory.free=212MB
os.memory.max=889MB
os.memory.total=240MB
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
二、java api操作
以下为常见的操作说明
1、CRUD示例
其他的创建工程什么的都忽略,本示例仅仅描述该应用所需要的文件或内容。
1、pom.xml
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.7.1</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
2、App.java
package org.zookeeperdemo;
import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
public class App {
// 会话超时时间,设置为与系统默认时间一致
private static final int SESSION_TIMEOUT = 30000;
// 创建 ZooKeeper 实例
ZooKeeper zk;
// 创建 Watcher 实例
Watcher wh = new Watcher() {
public void process(org.apache.zookeeper.WatchedEvent event) {
System.out.println(event.toString());
}
};
// 初始化 ZooKeeper 实例
private void createZKInstance() throws IOException {
zk = new ZooKeeper("192.168.10.41:2118,192.168.10.42:2118,192.168.10.43:2118", App.SESSION_TIMEOUT, this.wh);
}
private void ZKOperations() throws IOException, InterruptedException, KeeperException {
System.out.println("/n1. 创建 ZooKeeper 节点 (znode : zoo2, 数据: myData2 ,权限: OPEN_ACL_UNSAFE ,节点类型: Persistent");
zk.create("/zoo2", "myData2".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("/n2. 查看是否创建成功: ");
System.out.println(new String(zk.getData("/zoo2", false, null)));
System.out.println("/n3. 修改节点数据 ");
zk.setData("/zoo2", "shenlan211314".getBytes(), -1);
System.out.println("/n4. 查看是否修改成功: ");
System.out.println(new String(zk.getData("/zoo2", false, null)));
System.out.println("/n5. 删除节点 ");
zk.delete("/zoo2", -1);
System.out.println("/n6. 查看节点是否被删除: ");
System.out.println(" 节点状态: [" + zk.exists("/zoo2", false) + "]");
}
private void ZKClose() throws InterruptedException {
zk.close();
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
App dm = new App();
dm.createZKInstance();
dm.ZKOperations();
dm.ZKClose();
}
}
- 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
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
三、分布式应用HA的服务协调器
服务端注册的为临时节点,客户端监控服务端注册的服务节点。
应用,server端相当于一个服务器启动了,并且注册到zookeeper,节点为临时有序节点,data为其服务器名称或ip,clent监控serverList,看是否有上线或下线的服务节点,如此达到服务的注册与发现。
1、pom.xml
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>3.7.1version>
dependency>
- 1
- 2
- 3
- 4
- 5
- 6
2、服务端AppServer.java
package com.win.ha;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
/**
* @author alanchan
*
*/
public class AppServer {
private String serverNode = "serverList";
private String subNode = "sub";
public void connectZookeeper(String nodeData) throws Exception {
ZooKeeper zk = new ZooKeeper("192.168.10.41:2118,192.168.10.42:2118,192.168.10.43:2118", 5000, new Watcher() {
public void process(WatchedEvent event) {
// 不做处理
}
});
// 在"/serverList"下创建子节点
// 子节点的类型设置为EPHEMERAL_SEQUENTIAL, 表明这是一个临时节点, 且在子节点的名称后面加上一串数字后缀
// 将server的地址数据关联到新创建的子节点上
// create: /serverList/sub0000000000
String createdPath = zk.create("/" + serverNode + "/" + subNode, nodeData.getBytes("utf-8"), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("create: " + createdPath);
}
public void handle() throws InterruptedException {
Thread.sleep(Long.MAX_VALUE);
}
public static void main(String[] args) throws Exception {
// 由于是二级节点,所以需要先创建serverList节点,该服务才能正常运行
// create /serverList
// 运行结果如下:
// [zk: server2:2118(CONNECTED) 30] ls /serverList
// [sub0000000000]
// [zk: server2:2118(CONNECTED) 31] get /serverList/sub0000000000
// server_name
AppServer as = new AppServer();
as.connectZookeeper("server_name:server2");
as.handle();
}
}
- 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
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
3、客户端AppClient.java
package com.win.ha;
import java.util.ArrayList;
import java.util.List;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
/**
* @author alanchan
*
*/
public class AppClient {
private String serverList = "serverList";
private ZooKeeper zk;
private Stat stat = new Stat();
private volatile List<String> nodeList;
/**
* 连接zookeeper
*
* @throws Exception
*/
public void connectZookeeper() throws Exception {
zk = new ZooKeeper("192.168.10.41:2118,192.168.10.42:2118,192.168.10.43:2118", 5000, new Watcher() {
public void process(WatchedEvent event) {
// 如果发生了"/serverList"节点下的子节点变化事件, 更新server列表, 并重新注册监听
if (event.getType() == EventType.NodeChildrenChanged && ("/" + serverList).equals(event.getPath())) {
try {
updateServerList();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
updateServerList();
}
/**
* 更新服务器列表
*
* @throws Exception
*/
private void updateServerList() throws Exception {
List<String> newServerList = new ArrayList<String>();
// 获取并监听serverList的子节点变化
// watch参数为true, 表示监听子节点变化事件.
// 每次都需要重新注册监听, 因为一次注册, 只能监听一次事件, 如果还想继续保持监听, 必须重新注册
List<String> subList = zk.getChildren("/"+serverList, true);
for (String subNode : subList) {
// 获取每个子节点下关联的server地址
byte[] data = zk.getData("/" + serverList + "/" + subNode, false, stat);
newServerList.add(new String(data, "utf-8"));
System.out.println("serverName:"+new String(data,"utf-8"));
}
// 替换server列表
nodeList = newServerList;
System.out.println("server list updated: " + serverList);
}
/**
* client的工作逻辑写在这个方法中 此处不做任何处理, 只让client sleep
*/
public void handle() throws InterruptedException {
Thread.sleep(Long.MAX_VALUE);
}
public static void main(String[] args) throws Exception {
AppClient ac = new AppClient();
ac.connectZookeeper();
ac.handle();
// ZooKeeper zk = new ZooKeeper("192.168.10.41:2118,192.168.10.42:2118,192.168.10.43:2118", 100, new Watcher() {
//
// @Override
// public void process(WatchedEvent event) {
//
// }});
// List subList = zk.getChildren("/serverList", true);
// System.out.println(subList);
}
}
- 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
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
4、验证
前提:zookeeper服务都是正常启动的。
1、启动两个AppServer.java服务
AppServer1运行结果:
create: /serverList/sub0000000000
AppServer2运行结果:
create: /serverList/sub0000000001
- 1
- 2
- 3
- 4
2、启动一个AppClient.java服务
运行结果:
serverName:server_name:server2
serverName:server_name:server2
server list updated: serverList
- 1
- 2
- 3
评论记录:
回复评论: