2、zookeeper基本操作及应用示例(shell、java api、应用场景示例)

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、查看目录 ls命令

[zk: server2:2118(CONNECTED) 2] ls /
[zookeeper]

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 子节点个数

3、创建目录(创建一个新的 znode )

[zk: server1:2118(CONNECTED) 2] create /zk testdata
Created /zk

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

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

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

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

8、删除znode

[zk: server2:2118(CONNECTED) 10] delete /zk
[zk: server2:2118(CONNECTED) 11] ls /
[zookeeper]

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

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

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]

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]

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]

(三)、Zookeeper 四字命令

zookeeper 支持某些特定的四字命令与其交互,用户获取 zookeeper 服务的当前状态及相关信息,用户在客户端可以通过 telenet 或者 nc(netcat) 向 zookeeper 提交相应的命令。

1、安装nc

$ yum install nc                # centos
# 或
$ sudo apt install netcat       # ubuntu

2、配置zookeeper的配置文件

vim conf/zoo.cfg

# 配置文件中增加一行
4lw.commands.whitelist=*
# 需要重启zookeeper

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

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]$ 

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

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 

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

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

二、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>

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();
	}

}

三、分布式应用HA的服务协调器

服务端注册的为临时节点,客户端监控服务端注册的服务节点。
应用,server端相当于一个服务器启动了,并且注册到zookeeper,节点为临时有序节点,data为其服务器名称或ip,clent监控serverList,看是否有上线或下线的服务节点,如此达到服务的注册与发现。

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>

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();

	}

}

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<String> subList = zk.getChildren("/serverList", true);
//		System.out.println(subList);
	}

}

4、验证

前提:zookeeper服务都是正常启动的。
1、启动两个AppServer.java服务

AppServer1运行结果:
create: /serverList/sub0000000000
AppServer2运行结果:
create: /serverList/sub0000000001

2、启动一个AppClient.java服务
运行结果:

serverName:server_name:server2
serverName:server_name:server2
server list updated: serverList
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一瓢一瓢的饮 alanchanchn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值