ZooKeeper之Java API的基本使用以及常见应用场景的实现

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第13篇文章,点击查看活动详情

Java API的基本使用

添加依赖

	  <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.7.0</version>
        </dependency>
复制代码

创建ZK连接

@SpringBootTest
public class ZKTest {

    /**
     * 获取zookeeper连接时所需要的服务器连接信息,格式为主机名:端口号;多个服务使用“,”分割
     */
    public final String CONNECT_STRING = "127.0.0.1:2181";

    /**
     * 请求会话超时时长
     */
    public final int SESSIONT_IMEOUT = 5000;

    private ZooKeeper zk;
    
    private String path = "/zk";
    
    private String sonPath = "/zk/son";
    
    private String value = "zk_Data";

    /**
     * 获取ZooKeeper链接
     *
     * @return
     * @throws Exception
     */
    @Before
    public void getZKConnection() throws Exception {
        zk = new ZooKeeper(CONNECT_STRING, SESSIONT_IMEOUT, null);
    }

    /**
     * 关闭ZK连接
     *
     * @throws InterruptedException
     */
    @After
    public void closeZKConnection() throws InterruptedException {
        zk.close();
    }
}
复制代码

创建持久不带序列编号的节点

    @Test
    public void createZKNode1() throws Exception {
        // 四个参数: 节点路径,节点数据,权限信息,节点的类型
        zk.create(path, value.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    }
复制代码

创建持久带序列编号的节点

    @Test
    public void createZKNode2() throws Exception {
        // 四个参数: 节点路径,节点数据,权限信息,节点的类型
        zk.create(path, value.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
        zk.create(path, value.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
        zk.create(path, value.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
    }
复制代码

创建临时不带序列编号的节点

    @Test
    public void createZKNode3() throws Exception {
        // 四个参数: 节点路径,节点数据,权限信息,节点的类型
        zk.create(path, value.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    }
复制代码

创建临时带序列编号的节点

    @Test
    public void createZKNode4() throws Exception {
        // 四个参数: 节点路径,节点数据,权限信息,节点的类型
        zk.create(path, value.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        zk.create(path, value.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        zk.create(path, value.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
    }
复制代码

查看节点数据

    @Test
    public void getZNodeData() throws Exception {
        String znodeData = new String(zk.getData(path, false, null));
        System.out.println("查看节点数据:" + znodeData);
    }
复制代码

修改节点数据

    @Test
    public void updateZNodeData() throws Exception {
        String value="update_data";
        zk.setData(path, value.getBytes(), -1);
        String newData = new String(zk.getData(path, false, null));
        if (newData.equals(value)) {
            System.out.println("修改节点数据: " + true);
        } else {
            System.out.println("修改节点数据: " + false);
        }
    }
复制代码

判断节点是否存在

    @Test
    public void existsZNode() throws Exception {
        boolean existsZNode = (zk.exists(path, false) != null) ? true : false;
        System.out.println("判断节点是否存在: " + existsZNode);
    }
复制代码

查看节点的子节点列表

    @Test
    public void getChildrenZNodes() throws Exception {
        zk.create(sonPath, value.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        List<String> children = zk.getChildren(path, false);
        for (String child : children) {
            System.out.println("查看节点的子节点列表: " + child);
        }
    }
复制代码

删除节点

    @Test
    public void deleteZNode() {
        try {
            zk.delete(path, -1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
        System.out.println("删除znode节点成功");
    }
复制代码

级联删除节点

    @Test
    public void deleteAllNode() throws Exception {
        zk.create(path, value.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zk.create(sonPath, value.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        this.deleteAllNode(this.path);
    }

    /**
     * 删除一个节点,不管有有没有任何子节点
     *
     * @return
     * @throws Exception
     */
    public void deleteAllNode(String path) throws Exception {
        if (zk.exists(path, null) == null) {
            System.out.println("该路径 " + path + " 不存在");
        }

        List<String> children = zk.getChildren(path, null);
        if (children.size() == 0) {
            zk.delete(path, -1);
        } else {
            // 删除child路径下的所有子节点,但是并不删除child节点
            for (String child : children) {
                String deletePath = path + "/" + child;
                deleteAllNode(deletePath);
            }
            // 节点所有子节点删除之后,直接当前节点
            zk.delete(path, -1);
        }
    }
复制代码

级联创建节点

    @Test
    public void createAllNode() throws Exception {
        this.createAllNode(this.sonPath);
    }

    /**
     * 级联创建任意节点
     *
     * @throws Exception
     */
    public boolean createAllNode(String znodePath) throws Exception {
        // 判断该节点是否存在,如果存在,则不创建
        if (zk.exists(znodePath, null) != null) {
            return false;
        } else {
            try {
                // 直接创建,捕捉异常,根据对应的异常如果是发现没有父节点,那么就创建父节点
                zk.create(znodePath, value.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            } catch (KeeperException e) {
                // 截取父节点
                String parentPath = znodePath.substring(0, znodePath.lastIndexOf("/"));
                // 创建父节点
                createAllNode(parentPath);
                try {
                    // 父节点创建好后,创建该节点
                    zk.create(znodePath, value.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                } catch (KeeperException e1) {
                    e1.printStackTrace();
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return true;
    }
复制代码

清空子节点

 @Test
    public void clearChildNode() throws Exception {
        this.clearChildNode(this.path);
    }

    /**
     * 清空子节点
     *
     * @throws Exception
     */
    public boolean clearChildNode(String path) throws Exception {
        List<String> children = zk.getChildren(path, null);
        for (String child : children) {
            String childNode = path + "/" + child;
            if (zk.getChildren(childNode, null).size() != 0) {
                clearChildNode(childNode);
            }
            zk.delete(childNode, -1);
        }
        return true;
    }
复制代码

实现节点监听

ZooKeeper可以作为注册中心,原因就在于其可以实现节点监听。

比如:在分布式系统中,一个服务启动后就可以向ZK注册中心的某个节点注册,记录服务器的信息,服务下线则删除节点下记录的服务器信息。

创建监听节点

    private String sonPath = "/watch_zk/son";
    
    private String value = "zk_Data";
    
    private String watchPath = "/watch_zk";

    @Test
    public void createWatchNode() throws Exception {
        zk.create(watchPath, value.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    }
复制代码

实现监听

public class ZKWatch {

    /**
     * 获取zookeeper连接时所需要的服务器连接信息,格式为主机名:端口号;多个服务使用“,”分割
     */
    public static final String CONNECT_STRING = "127.0.0.1:2181";

    /**
     * 请求会话超时时长
     */
    public static final int SESSIONT_IMEOUT = 5000;

    private static ZooKeeper zk;

    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        String watchPath = "/watch_zk";
        zk = new ZooKeeper(CONNECT_STRING, SESSIONT_IMEOUT, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                // 事件类型
                Event.EventType type = event.getType();
                // 节点路径
                String path = event.getPath();
                System.out.println("节点路径 = " + path+" 事件类型 = " + type);

                try {
                    // 注册监听 节点的数据变化
                    // 事件: NodeDeleted, NodeDataChanged
                    // 触发: delete, setData
                    zk.getData(watchPath, true, null);

                    // 注册监听 子节点个数变化
                    // 事件: NodeChildrenChanged, NodeDeleted
                    // 触发: create/delete子节点, delete当前给定节点
                    zk.getChildren(watchPath, true);

                    // 注册监听 该节点的变化(被创建,被删除,数据被改变)
                    // 事件: NodeCreated, NodeDeleted, NodeDataChanged
                    // 触发: create,  delete,  setData
                    zk.exists(watchPath, true);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                // 根据监听的相应的事件类型和节点,编写对应业务逻辑
                if (type == Event.EventType.NodeDeleted && event.getPath().equals(watchPath)) {
                    System.out.println("节点的数据变化---删除");
                } else if (type == Event.EventType.NodeDataChanged) {
                    System.out.println("节点的数据变化---修改");
                } else if (type == Event.EventType.NodeCreated) {
                    System.out.println("节点的数据变化---创建");
                } else if (type == Event.EventType.NodeChildrenChanged) {
                    System.out.println("子节点个数变化---创建/删除");
                } else if (type == Event.EventType.NodeDeleted) {
                    System.out.println("子节点个数变化---删除");
                }

            }
        });

        // 判断监听节点是否,不存在则创建
        if (zk.exists(watchPath, null) == null) {
            zk.create(watchPath, "watchData".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }

        // 保证watcer线程一直工作
        Thread.sleep(Long.MAX_VALUE);

        // 启动监听就不会关闭zk链接
        // zk.close();
    }
}
复制代码

执行测试

    @Test
    public void createZKNode() throws Exception {
        zk.setData(watchPath,value.getBytes(),-1);

        zk.create(sonPath, value.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zk.setData(sonPath,value.getBytes(),-1);
        zk.delete(sonPath,-1);
    }
复制代码
15:31:05.201 [main] INFO org.apache.zookeeper.ZooKeeper - Initiating client connection, connectString=127.0.0.1:2181 sessionTimeout=5000 watcher=com.example.demo.zk.ZKWatch$1@23e028a9
15:31:05.206 [main] INFO org.apache.zookeeper.common.X509Util - Setting -D jdk.tls.rejectClientInitiatedRenegotiation=true to disable client-initiated TLS renegotiation
15:31:05.576 [main] INFO org.apache.zookeeper.ClientCnxnSocket - jute.maxbuffer value is 1048575 Bytes
15:31:05.618 [main] INFO org.apache.zookeeper.ClientCnxn - zookeeper.request.timeout value is 0. feature enabled=false
15:31:05.624 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.SaslServerPrincipal - Canonicalized address to activate.navicat.com
15:31:05.625 [main-SendThread(127.0.0.1:2181)] INFO org.apache.zookeeper.ClientCnxn - Opening socket connection to server activate.navicat.com/127.0.0.1:2181.
15:31:05.626 [main-SendThread(127.0.0.1:2181)] INFO org.apache.zookeeper.ClientCnxn - SASL config status: Will not attempt to authenticate using SASL (unknown error)
15:31:05.627 [main-SendThread(127.0.0.1:2181)] INFO org.apache.zookeeper.ClientCnxn - Socket connection established, initiating session, client: /127.0.0.1:2955, server: activate.navicat.com/127.0.0.1:2181
15:31:05.628 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Session establishment request sent on activate.navicat.com/127.0.0.1:2181
15:31:05.633 [main-SendThread(127.0.0.1:2181)] INFO org.apache.zookeeper.ClientCnxn - Session establishment complete on server activate.navicat.com/127.0.0.1:2181, session id = 0x1000f36f14d001b, negotiated timeout = 5000
节点路径 = null 事件类型 = None
15:31:05.638 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 1,4  replyHeader:: 1,300,0  request:: '/watch_zk,T  response:: #7a6b5f44617461,s{290,295,1661412554041,1661412576797,1,2,0,0,7,0,298} 
15:31:05.642 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 2,8  replyHeader:: 2,300,0  request:: '/watch_zk,T  response:: v{} 
15:31:05.644 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 3,3  replyHeader:: 3,300,0  request:: '/watch_zk,T  response:: s{290,295,1661412554041,1661412576797,1,2,0,0,7,0,298} 
15:31:07.311 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x1000f36f14d001b after 0ms.
15:31:08.977 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x1000f36f14d001b after 0ms.
15:31:09.104 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x1000f36f14d001b
15:31:09.105 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeDataChanged path:/watch_zk for session id 0x1000f36f14d001b
节点路径 = /watch_zk 事件类型 = NodeDataChanged
15:31:09.107 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 4,4  replyHeader:: 4,303,0  request:: '/watch_zk,T  response:: #7a6b5f44617461,s{290,303,1661412554041,1661412669092,2,2,0,0,7,0,298} 
15:31:09.108 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 5,8  replyHeader:: 5,303,0  request:: '/watch_zk,T  response:: v{} 
15:31:09.109 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 6,3  replyHeader:: 6,303,0  request:: '/watch_zk,T  response:: s{290,303,1661412554041,1661412669092,2,2,0,0,7,0,298} 
节点的数据变化---修改
15:31:09.113 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x1000f36f14d001b
15:31:09.114 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/watch_zk for session id 0x1000f36f14d001b
节点路径 = /watch_zk 事件类型 = NodeChildrenChanged
15:31:09.114 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 7,4  replyHeader:: 7,304,0  request:: '/watch_zk,T  response:: #7a6b5f44617461,s{290,303,1661412554041,1661412669092,2,3,0,0,7,1,304} 
15:31:09.117 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 8,8  replyHeader:: 8,305,0  request:: '/watch_zk,T  response:: v{'son} 
15:31:09.119 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 9,3  replyHeader:: 9,305,0  request:: '/watch_zk,T  response:: s{290,303,1661412554041,1661412669092,2,3,0,0,7,1,304} 
子节点个数变化---创建/删除
15:31:09.119 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x1000f36f14d001b
15:31:09.119 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/watch_zk for session id 0x1000f36f14d001b
节点路径 = /watch_zk 事件类型 = NodeChildrenChanged
15:31:09.120 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 10,4  replyHeader:: 10,306,0  request:: '/watch_zk,T  response:: #7a6b5f44617461,s{290,303,1661412554041,1661412669092,2,4,0,0,7,0,306} 
15:31:09.122 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 11,8  replyHeader:: 11,307,0  request:: '/watch_zk,T  response:: v{} 
15:31:09.123 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d001b, packet:: clientPath:null serverPath:null finished:false header:: 12,3  replyHeader:: 12,307,0  request:: '/watch_zk,T  response:: s{290,303,1661412554041,1661412669092,2,4,0,0,7,0,306} 
子节点个数变化---创建/删除
15:31:10.789 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x1000f36f14d001b after 0ms.
复制代码

实现分布式共享锁

分布式业务系统中,可能会存在某种资源,需要被整个系统的各台服务器共享访问,但是只允许一台服务器同时访问,此时就可以使用ZK实现分布式共享锁。

编写共享锁逻辑

public class ZkLock {

	/**
	 * 获取zookeeper连接时所需要的服务器连接信息,格式为主机名:端口号;多个服务使用“,”分割
	 */
	public static final String CONNECT_STRING = "127.0.0.1:2181";

	/**
	 * 请求会话超时时长
	 */
	public static final int SESSIONT_IMEOUT = 5000;
	/**
	 * 定义父节点锁
	 */
	private static final String PARENT_NODE = "/parent_locks";
	/**
	 * 定义客户端节点
	 * 会有多个客户端节点抢着注册,且是有序编号的客户端节点
	 * 谁拿到当前子客户端节点则意外拿到锁
	 */
	private static final String SUB_NODE = "/sub_client";
	/**
	 * ZK连接
	 */
	static ZooKeeper zk = null;
	/**
	 * 当前注册子客户端
	 */
	private static String currentPath = "";

	public static void main(String[] args) throws Exception {
		ZkLock zklock = new ZkLock();
		//  获取zookeeper链接
		zklock.getZookeeperConnect();

		// 父节点是否存在,不存在则创建
		Stat exists = zk.exists(PARENT_NODE, false);
		if (exists == null) {
			zk.create(PARENT_NODE, PARENT_NODE.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		}

		// 监听父节点
		zk.getChildren(PARENT_NODE, true);

		// 往父节点下注册节点,注册临时节点,好处:当宕机或者断开链接时该节点自动删除
		currentPath = zk.create(PARENT_NODE + SUB_NODE, SUB_NODE.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

		// 测试故一直监听
		Thread.sleep(Long.MAX_VALUE);
		// 关闭zk链接
		zk.close();
	}

	/**
	 * 获取zookeeper链接,同时进行监听
	 */
	public void getZookeeperConnect() throws Exception {
		zk = new ZooKeeper(CONNECT_STRING, SESSIONT_IMEOUT, new Watcher() {
			@Override
			public void process(WatchedEvent event) {
				// 子节点变化,且是监听的路径
				if (event.getType() == EventType.NodeChildrenChanged && event.getPath().equals(PARENT_NODE)) {
					try {
						// 获取父节点下所有子节点, 并继续监听
						List<String> childrenNodes = zk.getChildren(PARENT_NODE, true);
						// 将创建的子客户端节点进行排序,自然排序,即从小到大
						Collections.sort(childrenNodes);
						System.out.println("当前注册子客户端锁节点:"+currentPath);
						System.out.println("父节点下已注册子客户端节点: "+childrenNodes);
						// 如果当前子客户端节点与父节点下所以子节点客户端经过排序后的第一个子客户端相等,则进行业务处理
						if ((PARENT_NODE + "/" + childrenNodes.get(0)).equals(currentPath)) {
							System.out.println("从父节点下获取排序最小节点:"+ childrenNodes.get(0)+" 执行业务");
							// 业务处理
							handleBusiness(currentPath);
						}else{
							System.out.println("注册子客户端节点: "+childrenNodes.stream().skip(1).collect(Collectors.toList())+"获取锁失败...");
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		});
	}

	public void handleBusiness(String deletePath) throws Exception {
		System.out.println("业务处理开始....");
		// 模拟业务耗时
		Thread.sleep(new Random().nextInt(5000));
		// 业务完成删除当前子客户端节点
		zk.delete(deletePath, -1);
		System.out.println("业务处理结束,删除锁节点:"+deletePath);

		// 给与一定时间,再次打乱服务器抢子客户端节点锁的顺序
		Thread.sleep(new Random().nextInt(4000));
		// 抢资源锁
		currentPath = zk.create(PARENT_NODE + SUB_NODE, SUB_NODE.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
		System.out.println("子客户端节点获取锁:"+currentPath);
	}
}

复制代码

执行测试

同时启动3个线程执行上述代码。

17:06:35.439 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x1000f36f14d0033 after 0ms.
17:06:35.573 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x1000f36f14d0033
17:06:35.573 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/parent_locks for session id 0x1000f36f14d0033
17:06:35.573 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d0033, packet:: clientPath:null serverPath:null finished:false header:: 11,8  replyHeader:: 11,827,0  request:: '/parent_locks,T  response:: v{'sub_client0000000233,'sub_client0000000231,'sub_client0000000232} 
当前注册子客户端锁节点:/parent_locks/sub_client0000000232
父节点下已注册子客户端节点: [sub_client0000000231, sub_client0000000232, sub_client0000000233]
注册子客户端节点: [sub_client0000000232, sub_client0000000233]获取锁失败...
17:06:37.018 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x1000f36f14d0033
17:06:37.019 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/parent_locks for session id 0x1000f36f14d0033
17:06:37.019 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x1000f36f14d0033 after 0ms.
17:06:37.019 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d0033, packet:: clientPath:null serverPath:null finished:false header:: 12,8  replyHeader:: 12,828,0  request:: '/parent_locks,T  response:: v{'sub_client0000000233,'sub_client0000000232} 
当前注册子客户端锁节点:/parent_locks/sub_client0000000232
父节点下已注册子客户端节点: [sub_client0000000232, sub_client0000000233]
从父节点下获取排序最小节点:sub_client0000000232 执行业务
业务处理开始....
17:06:37.228 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x1000f36f14d0033
17:06:37.228 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/parent_locks for session id 0x1000f36f14d0033
17:06:37.228 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d0033, packet:: clientPath:null serverPath:null finished:false header:: 13,2  replyHeader:: 13,829,0  request:: '/parent_locks/sub_client0000000232,-1  response:: null
业务处理结束,删除锁节点:/parent_locks/sub_client0000000232
17:06:38.893 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x1000f36f14d0033 after 0ms.
17:06:39.329 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d0033, packet:: clientPath:null serverPath:null finished:false header:: 14,1  replyHeader:: 14,830,0  request:: '/parent_locks/sub_client,#2f7375625f636c69656e74,v{s{31,s{'world,'anyone}}},3  response:: '/parent_locks/sub_client0000000234 
子客户端节点获取锁:/parent_locks/sub_client0000000234
17:06:39.330 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d0033, packet:: clientPath:null serverPath:null finished:false header:: 15,8  replyHeader:: 15,830,0  request:: '/parent_locks,T  response:: v{'sub_client0000000233,'sub_client0000000234} 
当前注册子客户端锁节点:/parent_locks/sub_client0000000234
父节点下已注册子客户端节点: [sub_client0000000233, sub_client0000000234]
注册子客户端节点: [sub_client0000000234]获取锁失败...
17:06:40.597 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x1000f36f14d0033
17:06:40.598 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/parent_locks for session id 0x1000f36f14d0033
17:06:40.598 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x1000f36f14d0033 after 0ms.
17:06:40.598 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x1000f36f14d0033, packet:: clientPath:null serverPath:null finished:false header:: 16,8  replyHeader:: 16,831,0  request:: '/parent_locks,T  response:: v{'sub_client0000000235,'sub_client0000000233,'sub_client0000000234} 
当前注册子客户端锁节点:/parent_locks/sub_client0000000234
父节点下已注册子客户端节点: [sub_client0000000233, sub_client0000000234, sub_client0000000235]
注册子客户端节点: [sub_client0000000234, sub_client0000000235]获取锁失败...
17:06:41.496 [main-SendThread(127.0.0.1:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x1000f36f14d0033
17:06:41.496 [main-SendThread(127.0.0.1:2181)]
复制代码

实现配置功能

实现客户端对配置信息进行 添加 修改 删除的操作

实现逻辑

public class DataNodeConfig {

    /**
     * 获取zookeeper连接时所需要的服务器连接信息,格式为主机名:端口号;多个服务使用“,”分割
     */
    public static final String CONNECT_STRING = "node01:2181,node02:2182,node03:2183";
    /**
     * 请求会话超时时长
     */
    public static final int SESSIONT_IMEOUT = 5000;
    /**
     * 配置节点
     */
    private static final String PARENT_NODE = "/config";
    static List<String> oldChildNodeList = null;
    static ZooKeeper zk = null;

    public static void main(String[] args) throws Exception {
        zk = new ZooKeeper(CONNECT_STRING, SESSIONT_IMEOUT, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                EventType type = event.getType();
                String path = event.getPath();
                KeeperState state = event.getState();
                /**
                 * 排除获取连接时的触发: 即type:None path: null
                 */
                if (state.getIntValue() == 3 && path != null) {
                    // 子节点的列表信息
                    List<String> newChildNodeList = null;
                    try {
                        newChildNodeList = zk.getChildren(PARENT_NODE, true);
                    } catch (KeeperException e1) {
                        e1.printStackTrace();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }

                    /**
                     * 虽然此处响应的逻辑有可能是 添加 或者删除, 但是经过判断之后,如果是删除,不做任何处理
                     * 如果添加,那么做对应的业务处理
                     */
                    if (path.equals(PARENT_NODE) && type == EventType.NodeChildrenChanged) {
                        // 添加
                        if (oldChildNodeList.size() < newChildNodeList.size()) {
                            List<String> newList = newChildNodeList.stream().filter(s -> !oldChildNodeList.contains(s)).collect(Collectors.toList());
                            String newAdd = newList.get(0);
                            byte[] data = null;
                            try {
                                data = zk.getData(PARENT_NODE + "/" + newAdd, true, null);
                            } catch (KeeperException e) {
                                e.printStackTrace();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println("新曾一项配置: key=" + newAdd + ", value=" + new String(data));
                        }

                        /**
                         * 父节点下的一个子节点的删除变化事件
                         */
                    } else {
                        for (String child : oldChildNodeList) {
                            String childPath = PARENT_NODE + "/" + child;
                            if (path.equals(childPath) && type == EventType.NodeDeleted) {
                                List<String> finalNewChildNodeList = newChildNodeList;
                                List<String> newList = oldChildNodeList.stream().filter(s -> !finalNewChildNodeList.contains(s)).collect(Collectors.toList());
                                String delete = newList.get(0);
                                System.out.println("删除一项配置: key=" + delete);
                            }
                        }
                    }

                    /**
                     * 父节点下的一个子节点的数据修改变化事件
                     */
                    for (String child : oldChildNodeList) {
                        String childPath = PARENT_NODE + "/" + child;
                        if (path.equals(childPath) && type == EventType.NodeDataChanged) {
                            byte[] data = null;
                            try {
                                data = zk.getData(childPath, true, null);
                            } catch (KeeperException e) {
                                e.printStackTrace();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            String newValue = new String(data);
                            System.out.println("修改一项配置: key=" + child + ", newValue=" + newValue);
                            break;
                        }
                    }
                    /**
                     * 新老子节点列表的迭代
                     */
                    oldChildNodeList = newChildNodeList;
                }
            }
        });

        Stat exists = zk.exists(PARENT_NODE, null);
        if (exists == null) {
            zk.create(PARENT_NODE, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }

        /**
         * 添加监听
         *
         * 1、/config节点的NodeChildrenChanged
         *
         * 2、/config节点下的子节点的NodeDataChanged
         */
        oldChildNodeList = zk.getChildren(PARENT_NODE, true);
        for (String child : oldChildNodeList) {
            String childPath = PARENT_NODE + "/" + child;
            // 添加子节点的 NodeDataChanged
            zk.getData(childPath, true, null);
        }

        Thread.sleep(Long.MAX_VALUE);
    }
}

复制代码

执行测试

public class Client {

    /**
     * 获取zookeeper连接时所需要的服务器连接信息,格式为主机名:端口号;多个服务使用“,”分割
     */
    public static final String CONNECT_STRING = "node01:2181,node02:2182,node03:2183";
    /**
     * 请求会话超时时长
     */
    public static final int SESSIONT_IMEOUT = 5000;
    /**
     * 配置节点
     */
    private static final String PARENT_NODE = "/config";

    public static void main(String[] args) throws Exception {
        /**
         * 获取zookeeper连接
         */
        ZooKeeper zk = new ZooKeeper(CONNECT_STRING, SESSIONT_IMEOUT, null);
        /**
         * 判断/config节点是否存在,不存在则创建
         */
        Stat exists = zk.exists(PARENT_NODE, null);
        if (exists == null) {
            zk.create(PARENT_NODE, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }

        /**
         * 实现 添加 修改 删除
         */
        String path = PARENT_NODE + "/" + "key";
        zk.create(path, "value".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        Thread.sleep(5 * 1000);
        zk.setData(path, "value".getBytes(), -1);

        Thread.sleep(5 * 1000);
        zk.delete(path, -1);

        Thread.sleep(100 * 1000);
        zk.close();
    }
}
复制代码
22:41:21.989 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010ac8dab0004, packet:: clientPath:null serverPath:null finished:false header:: 3,8  replyHeader:: 3,17179869263,0  request:: '/config,T  response:: v{'key} 
22:41:21.997 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010ac8dab0004, packet:: clientPath:null serverPath:null finished:false header:: 4,4  replyHeader:: 4,17179869263,0  request:: '/config/key,T  response:: #76616c7565,s{17179869263,17179869263,1661438481952,1661438481952,0,0,0,0,5,0,17179869263} 
新曾一项配置: key=key, value=value
22:41:23.664 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010ac8dab0004 after 0ms.
22:41:25.330 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010ac8dab0004 after 0ms.
22:41:26.960 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x20010ac8dab0004
22:41:26.960 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeDataChanged path:/config/key for session id 0x20010ac8dab0004
22:41:26.960 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010ac8dab0004 after 0ms.
22:41:26.960 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010ac8dab0004, packet:: clientPath:null serverPath:null finished:false header:: 5,8  replyHeader:: 5,17179869264,0  request:: '/config,T  response:: v{'key} 
22:41:26.961 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010ac8dab0004, packet:: clientPath:null serverPath:null finished:false header:: 6,4  replyHeader:: 6,17179869264,0  request:: '/config/key,T  response:: #76616c7565,s{17179869263,17179869264,1661438481952,1661438486958,1,0,0,0,5,0,17179869263} 
修改一项配置: key=key, newValue=value
22:41:28.628 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010ac8dab0004 after 0ms.
22:41:30.294 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010ac8dab0004 after 0ms.
22:41:31.960 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010ac8dab0004 after 0ms.
22:41:31.967 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x20010ac8dab0004
22:41:31.967 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeDeleted path:/config/key for session id 0x20010ac8dab0004
22:41:31.967 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x20010ac8dab0004
22:41:31.967 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/config for session id 0x20010ac8dab0004
22:41:31.967 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010ac8dab0004, packet:: clientPath:null serverPath:null finished:false header:: 7,8  replyHeader:: 7,17179869265,0  request:: '/config,T  response:: v{} 
删除一项配置: key=key
22:41:31.969 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010ac8dab0004, packet:: clientPath:null serverPath:null finished:false header:: 8,8  replyHeader:: 8,17179869265,0  request:: '/config,T  response:: v{} 
22:41:33.635 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010ac8dab0004 after 0ms.
22:41:35.301 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010ac8dab0004 after 0ms.
复制代码

实现同步队列

实现逻辑

public class SyncQueueClient {

    /**
     * 获取zookeeper连接时所需要的服务器连接信息,格式为主机名:端口号;多个服务使用“,”分割
     */
    public static final String CONNECT_STRING = "node01:2181,node02:2182,node03:2183";
    /**
     * 请求会话超时时长
     */
    public static final int SESSIONT_IMEOUT = 5000;
    /**
     * 根节点
     */
    private static final String PARENT_NODE = "/syncQueue";
    /**
     * 需要队列元素个数
     */
    private static final int NEED_QUEUE = 5;

    private static ZooKeeper zk = null;

    private static int count = 0;

    public static void main(String[] args) throws Exception {
        // 获取zookeeper链接
        zk = new ZooKeeper(CONNECT_STRING, SESSIONT_IMEOUT, new Watcher() {

            @Override
            public void process(WatchedEvent event) {
                String path = event.getPath();
                EventType et = event.getType();
                // 跳过初始化监听事件
                if (path == null) {
                    return;
                }

                // 根节点下子节点数量变化
                if (path.equals(PARENT_NODE) && et == EventType.NodeChildrenChanged) {
                    // 判断队列元素是否达到一定数量
                    try {
                        List<String> children = zk.getChildren(PARENT_NODE, true);
                        int queueNumber = children.size();
                        if (queueNumber == NEED_QUEUE) {
                            for (String child : children) {
                                consume(child);
                            }
                        } else if (queueNumber < NEED_QUEUE) {
                            if (count == NEED_QUEUE) {
                                produce(true);
                            } else {
                                produce(false);
                            }
                        }
                        count = queueNumber;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        // 判断父节点是否存在,不存在则创建
        Stat exists = zk.exists(PARENT_NODE, false);
        if (exists == null) {
            zk.create(PARENT_NODE, PARENT_NODE.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }

        // 监听根节点
        zk.getChildren(PARENT_NODE, true);

        Thread.sleep(1000);
        produce(true);

        Thread.sleep(Long.MAX_VALUE);
        zk.close();
    }

    /**
     * 首先,我们的这个程序会一直监听PARENT_NODE,等待所监听的节点下的队列成员是否全部到达 如果满足条件,该业务方法才会执行
     * 这个条件是:
     * 1、该业务程序收到的某一个节点的某一个事件要满足我们监听的该节点
     * 2、队列的所有成员都达到
     */
    public static void produce(boolean tag) throws InterruptedException, KeeperException {
        String path = PARENT_NODE + "/" + UUID.randomUUID();
        if (tag) {
            System.out.println("队列为空,立即生产元素...");
            zk.create(path, path.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        } else {
            System.out.println("队列元素不足最低消费数量:" + NEED_QUEUE + ",准备生产...");
            Thread.sleep(2000);
            zk.create(path, path.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        }


    }

    public static void consume(String path) throws InterruptedException, KeeperException {
        zk.delete(PARENT_NODE + "/" + path, -1);
        System.out.println("消费队列中的元素: " + path);
    }
}
复制代码

执行测试

22:47:42.576 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 2,8  replyHeader:: 2,21474840890,0  request:: '/syncQueue,T  response:: v{} 
队列为空,立即生产元素...
22:47:43.586 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x10015dc638f0008
22:47:43.587 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/syncQueue for session id 0x10015dc638f0008
22:47:43.618 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 3,1  replyHeader:: 3,21474840891,0  request:: '/syncQueue/f5fbb385-5692-4a13-9511-e42826a6cac1,#2f73796e6351756575652f66356662623338352d353639322d346131332d393531312d653432383236613663616331,v{s{31,s{'world,'anyone}}},1  response:: '/syncQueue/f5fbb385-5692-4a13-9511-e42826a6cac1 
22:47:43.618 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x10015dc638f0008 after 34ms.
22:47:43.619 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 4,8  replyHeader:: 4,21474840891,0  request:: '/syncQueue,T  response:: v{'f5fbb385-5692-4a13-9511-e42826a6cac1} 
队列元素不足最低消费数量:5,准备生产...
22:47:45.285 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x10015dc638f0008 after 0ms.
22:47:45.621 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x10015dc638f0008
22:47:45.621 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/syncQueue for session id 0x10015dc638f0008
22:47:45.621 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 5,1  replyHeader:: 5,21474840892,0  request:: '/syncQueue/2f6f7502-cd3c-481e-aa2e-25fc4ddce589,#2f73796e6351756575652f32663666373530322d636433632d343831652d616132652d323566633464646365353839,v{s{31,s{'world,'anyone}}},1  response:: '/syncQueue/2f6f7502-cd3c-481e-aa2e-25fc4ddce589 
22:47:45.622 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 6,8  replyHeader:: 6,21474840892,0  request:: '/syncQueue,T  response:: v{'2f6f7502-cd3c-481e-aa2e-25fc4ddce589,'f5fbb385-5692-4a13-9511-e42826a6cac1} 
队列元素不足最低消费数量:5,准备生产...
22:47:47.289 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x10015dc638f0008 after 0ms.
22:47:47.624 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x10015dc638f0008
22:47:47.624 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/syncQueue for session id 0x10015dc638f0008
22:47:47.625 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 7,1  replyHeader:: 7,21474840893,0  request:: '/syncQueue/67816667-1952-4480-adbb-f5c4766a0998,#2f73796e6351756575652f36373831363636372d313935322d343438302d616462622d663563343736366130393938,v{s{31,s{'world,'anyone}}},1  response:: '/syncQueue/67816667-1952-4480-adbb-f5c4766a0998 
22:47:47.625 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 8,8  replyHeader:: 8,21474840893,0  request:: '/syncQueue,T  response:: v{'2f6f7502-cd3c-481e-aa2e-25fc4ddce589,'f5fbb385-5692-4a13-9511-e42826a6cac1,'67816667-1952-4480-adbb-f5c4766a0998} 
队列元素不足最低消费数量:5,准备生产...
22:47:49.293 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x10015dc638f0008 after 0ms.
22:47:49.628 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x10015dc638f0008
22:47:49.628 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/syncQueue for session id 0x10015dc638f0008
22:47:49.629 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 9,1  replyHeader:: 9,21474840894,0  request:: '/syncQueue/e956635a-259f-4695-8ea4-b7ea8ea8398f,#2f73796e6351756575652f65393536363335612d323539662d343639352d386561342d623765613865613833393866,v{s{31,s{'world,'anyone}}},1  response:: '/syncQueue/e956635a-259f-4695-8ea4-b7ea8ea8398f 
22:47:49.630 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 10,8  replyHeader:: 10,21474840894,0  request:: '/syncQueue,T  response:: v{'2f6f7502-cd3c-481e-aa2e-25fc4ddce589,'f5fbb385-5692-4a13-9511-e42826a6cac1,'67816667-1952-4480-adbb-f5c4766a0998,'e956635a-259f-4695-8ea4-b7ea8ea8398f} 
队列元素不足最低消费数量:5,准备生产...
22:47:51.296 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x10015dc638f0008 after 0ms.
22:47:51.631 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x10015dc638f0008
22:47:51.631 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/syncQueue for session id 0x10015dc638f0008
22:47:51.631 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 11,1  replyHeader:: 11,21474840895,0  request:: '/syncQueue/65bb9cc4-71da-412a-b105-39a4738f0e60,#2f73796e6351756575652f36356262396363342d373164612d343132612d623130352d333961343733386630653630,v{s{31,s{'world,'anyone}}},1  response:: '/syncQueue/65bb9cc4-71da-412a-b105-39a4738f0e60 
22:47:51.632 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 12,8  replyHeader:: 12,21474840895,0  request:: '/syncQueue,T  response:: v{'2f6f7502-cd3c-481e-aa2e-25fc4ddce589,'f5fbb385-5692-4a13-9511-e42826a6cac1,'65bb9cc4-71da-412a-b105-39a4738f0e60,'67816667-1952-4480-adbb-f5c4766a0998,'e956635a-259f-4695-8ea4-b7ea8ea8398f} 
22:47:51.635 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x10015dc638f0008
22:47:51.635 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/syncQueue for session id 0x10015dc638f0008
22:47:51.635 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 13,2  replyHeader:: 13,21474840896,0  request:: '/syncQueue/2f6f7502-cd3c-481e-aa2e-25fc4ddce589,-1  response:: null
消费队列中的元素: 2f6f7502-cd3c-481e-aa2e-25fc4ddce589
22:47:51.636 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 14,2  replyHeader:: 14,21474840897,0  request:: '/syncQueue/f5fbb385-5692-4a13-9511-e42826a6cac1,-1  response:: null
消费队列中的元素: f5fbb385-5692-4a13-9511-e42826a6cac1
22:47:51.638 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 15,2  replyHeader:: 15,21474840898,0  request:: '/syncQueue/65bb9cc4-71da-412a-b105-39a4738f0e60,-1  response:: null
消费队列中的元素: 65bb9cc4-71da-412a-b105-39a4738f0e60
22:47:51.639 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 16,2  replyHeader:: 16,21474840899,0  request:: '/syncQueue/67816667-1952-4480-adbb-f5c4766a0998,-1  response:: null
消费队列中的元素: 67816667-1952-4480-adbb-f5c4766a0998
22:47:51.641 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 17,2  replyHeader:: 17,21474840900,0  request:: '/syncQueue/e956635a-259f-4695-8ea4-b7ea8ea8398f,-1  response:: null
消费队列中的元素: e956635a-259f-4695-8ea4-b7ea8ea8398f
22:47:51.641 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 18,8  replyHeader:: 18,21474840900,0  request:: '/syncQueue,T  response:: v{} 
队列为空,立即生产元素...
22:47:51.642 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x10015dc638f0008
22:47:51.642 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/syncQueue for session id 0x10015dc638f0008
22:47:51.643 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 19,1  replyHeader:: 19,21474840901,0  request:: '/syncQueue/717427e7-6a2b-45bb-a2dd-c1b03f5f9669,#2f73796e6351756575652f37313734323765372d366132622d343562622d613264642d633162303366356639363639,v{s{31,s{'world,'anyone}}},1  response:: '/syncQueue/717427e7-6a2b-45bb-a2dd-c1b03f5f9669 
22:47:51.643 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x10015dc638f0008, packet:: clientPath:null serverPath:null finished:false header:: 20,8  replyHeader:: 20,21474840901,0  request:: '/syncQueue,T  response:: v{'717427e7-6a2b-45bb-a2dd-c1b03f5f9669} 
队列元素不足最低消费数量:5,准备生产...
22:47:53.309 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x10015dc638f0008 after 0ms.
复制代码

实现集群高可用

高可用实现

public class MasterHA {

    private static ZooKeeper zk = null;
    /**
     * 获取zookeeper连接时所需要的服务器连接信息,格式为主机名:端口号;多个服务使用“,”分割
     */
    public static final String CONNECT_STRING = "node01:2181,node02:2182,node03:2183";

    /**
     * 节点node01 node02 node03
     */
    private static final String HOSTNAME = "node01";

    /**
     * 请求会话超时时长
     */
    public static final int SESSIONT_IMEOUT = 5000;
    /**
     * 集群根节点
     */
    private static final String PARENT = "/cluster_ha";
    /**
     * 主节点根
     */
    private static final String ACTIVE = PARENT + "/active";
    /**
     * 从节点根
     */
    private static final String STANDBY = PARENT + "/standby";

    /**
     * 主节点
     */
    private static final String activeMasterPath = ACTIVE + "/" + HOSTNAME;
    /**
     * 从节点
     */
    private static final String standByMasterPath = STANDBY + "/" + HOSTNAME;
    /**
     * 锁节点
     */
    private static final String LOCK = PARENT + "/lock";

    /**
     * 临时节点类型
     */
    private static final CreateMode CME = CreateMode.EPHEMERAL;
    /**
     * 持久节点类型
     */
    private static final CreateMode CMP = CreateMode.PERSISTENT;

    public static void main(String[] args) throws Exception {
        System.out.println("-------------------------1.创建连接-------------------------");
        zk = new ZooKeeper(CONNECT_STRING, SESSIONT_IMEOUT, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                String path = event.getPath();
                EventType type = event.getType();
                if (path == null) {
                    return;
                }

                // 是ACTIVE根节点,且该节点下的主节点被删除
                if (path.equals(ACTIVE) && type == EventType.NodeChildrenChanged) {
                    System.out.println("-------------------------4.ACTIVE根节点下的主节点被删除-------------------------");
                    // active节点下的active master节点被删除后,自己就参与竞选active
                    if (getChildrenNumber(ACTIVE) == 0) {
                        System.out.println("-------------------------4-1." + HOSTNAME + " 准备参与竞选-------------------------");
                        // 注册一把独占锁,多个standby角色,谁注册成功,谁就应该切换成为active状态
                        try {
                            zk.exists(LOCK, true);
                        } catch (KeeperException e) {
                            e.printStackTrace();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // 创建节点, 数据存储对应节点信息
                        createZNode(LOCK, HOSTNAME, CME, "lock");
                    } else {
                        System.out.println("-------------------------4-2.ACTIVE根节点下的主节点刚被创建,放弃任何操作-------------------------");
                    }

                    // 做到循环监听
                    try {
                        zk.getChildren(ACTIVE, true);
                    } catch (KeeperException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                } else if (path.equals(LOCK) && type == EventType.NodeCreated) {
                    System.out.println("-------------------------5.锁被创建-------------------------");
                    // 获取节点数据
                    String nodeData = null;
                    try {
                        byte[] data = zk.getData(LOCK, false, null);
                        nodeData = new String(data);
                    } catch (Exception e) {
                    }

                    // 判断当前节点是否是自身创建,如果是就切换自己的状态为active
                    if (nodeData.equals(HOSTNAME)) {
                        createZNode(activeMasterPath, HOSTNAME, CME, null);
                        if (exists(standByMasterPath)) {
                            System.out.println("-------------------------5-1.当前节点" + HOSTNAME + "持有锁,切换状态为主节点-------------------------");
                            deleteZNode(standByMasterPath);
                        } else {
                            System.out.println("-------------------------5-2." + HOSTNAME + "成为主节点-------------------------");
                        }
                    } else {
                        System.out.println("-------------------------5-3.当前节点" + HOSTNAME + "未持有锁,放弃任务操作-------------------------");
                    }

                }
            }
        });


        System.out.println("-------------------------2.创建PARENT ACTIVE  STANDBY等根节点-------------------------");
        if (!exists(PARENT)) {
            createZNode(PARENT, PARENT, CMP, null);
        }
        if (!exists(ACTIVE)) {
            createZNode(ACTIVE, ACTIVE, CMP, null);
        }
        if (!exists(STANDBY)) {
            createZNode(STANDBY, STANDBY, CMP, null);
        }

        System.out.println("-------------------------3.判断ACTIVE节点下是否有子节点(主节点)-------------------------");
        // 判断ACTIVE节点下是否有子节点, 如果有则必定有主节点存在,没有则注册一把锁, 让自己竞选主节点
        if (getChildrenNumber(ACTIVE) == 0) {
            System.out.println("-------------------------3-1.没有子节点(主节点),准备争抢创建锁-------------------------");
            // 注册监听
            zk.exists(LOCK, true);
            // 创建争抢锁
            createZNode(LOCK, HOSTNAME, CME, null);
        } else {
            System.out.println("-------------------------3-2.存在子节点(主节点)," + HOSTNAME + "自动创建成为从节点-------------------------");
            createZNode(standByMasterPath, HOSTNAME, CME, null);
            // 注册监听, 监听active下子节点个数变化
            zk.getChildren(ACTIVE, true);
        }

        // 阻塞一直运行
        Thread.sleep(Long.MAX_VALUE);
    }

    private static void deleteZNode(String standbymasterpath) {
        try {
            zk.delete(standbymasterpath, -1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取子节点数量
     *
     * @param path
     * @return
     */
    public static int getChildrenNumber(String path) {
        int number = 0;
        try {
            number = zk.getChildren(path, null).size();
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return number;
    }

    /**
     * 判断节点是否存在
     */
    public static boolean exists(String path) {
        Stat exists = null;
        try {
            exists = zk.exists(path, null);
        } catch (KeeperException e) {
        } catch (InterruptedException e) {
        }
        if (exists == null) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 创建节点
     */
    public static void createZNode(String path, String data, CreateMode cm, String tag) {
        try {
            zk.create(path, data.getBytes(), Ids.OPEN_ACL_UNSAFE, cm);
        } catch (Exception e) {
            System.out.println("节点: " + path + " 创建失败或者节点已经存在");
            if (tag.equals("lock")) {
                System.out.println(HOSTNAME + " 未抢到锁,等待....");
            }
        }
    }
}

复制代码

启动node01

-------------------------1.创建连接-------------------------
21:39:42.899 [main] INFO org.apache.zookeeper.ZooKeeper - Client environment:zookeeper.version=3.7.0-e3704b390a6697bfdf4b0bef79e3da7a4f6bac4b, built on 2021-03-17 09:46 UTC
21:39:43.351 [main] INFO org.apache.zookeeper.ClientCnxn - zookeeper.request.timeout value is 0. feature enabled=false
-------------------------2.创建PARENT ACTIVE  STANDBY等根节点-------------------------
21:39:43.357 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.SaslServerPrincipal - Canonicalized address to activate.navicat.com
21:39:43.359 [main-SendThread(node02:2182)] INFO org.apache.zookeeper.ClientCnxn - Opening socket connection to server node02/127.0.0.1:2182.
21:39:43.381 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0003, packet:: clientPath:null serverPath:null finished:false header:: 3,3  replyHeader:: 3,8589934695,0  request:: '/cluster_ha/standby,F  response:: s{8589934621,8589934621,1661429857799,1661429857799,0,22,0,0,19,0,8589934694} 
-------------------------3.判断ACTIVE节点下是否有子节点(主节点)-------------------------
21:39:43.384 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0003, packet:: clientPath:null serverPath:null finished:false header:: 4,8  replyHeader:: 4,8589934695,0  request:: '/cluster_ha/active,F  response:: v{} 
-------------------------3-1.没有子节点(主节点),准备争抢创建锁-------------------------
21:39:43.386 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0003, packet:: clientPath:null serverPath:null finished:false header:: 5,3  replyHeader:: 5,8589934695,-101  request:: '/cluster_ha/lock,T  response::  
21:39:43.393 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x20010446d6e0003
21:39:43.394 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeCreated path:/cluster_ha/lock for session id 0x20010446d6e0003
-------------------------5.锁被创建-------------------------
21:39:43.395 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0003, packet:: clientPath:null serverPath:null finished:false header:: 6,1  replyHeader:: 6,8589934696,0  request:: '/cluster_ha/lock,#6e6f64653031,v{s{31,s{'world,'anyone}}},1  response:: '/cluster_ha/lock 
21:39:43.397 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0003, packet:: clientPath:null serverPath:null finished:false header:: 7,4  replyHeader:: 7,8589934696,0  request:: '/cluster_ha/lock,F  response:: #6e6f64653031,s{8589934696,8589934696,1661434783392,1661434783392,0,0,0,144133074155601923,6,0,8589934696} 
21:39:43.399 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0003, packet:: clientPath:null serverPath:null finished:false header:: 8,1  replyHeader:: 8,8589934697,0  request:: '/cluster_ha/active/node01,#6e6f64653031,v{s{31,s{'world,'anyone}}},1  response:: '/cluster_ha/active/node01 
21:39:43.400 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0003, packet:: clientPath:null serverPath:null finished:false header:: 9,3  replyHeader:: 9,8589934697,-101  request:: '/cluster_ha/standby/node01,F  response::  
-------------------------5-2.node01成为主节点-------------------------
21:39:45.066 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010446d6e0003 after 0ms.
21:39:46.733 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010446d6e0003 after 0ms.
复制代码

启动node02

-------------------------1.创建连接-------------------------
21:13:27.102 [main] INFO org.apache.zookeeper.ZooKeeper - Client environment:zookeeper.version=3.7.0-e3704b390a6697bfdf4b0bef79e3da7a4f6bac4b, built on 2021-03-17 09:46 UTC
21:41:43.282 [main] INFO org.apache.zookeeper.ClientCnxn - zookeeper.request.timeout value is 0. feature enabled=false
-------------------------2.创建PARENT ACTIVE  STANDBY等根节点-------------------------
21:41:43.286 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.SaslServerPrincipal - Canonicalized address to activate.navicat.com
21:41:43.288 [main-SendThread(node02:2182)] INFO org.apache.zookeeper.ClientCnxn - Opening socket connection to server node02/127.0.0.1:2182.
21:41:43.309 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0004, packet:: clientPath:null serverPath:null finished:false header:: 3,3  replyHeader:: 3,8589934698,0  request:: '/cluster_ha/standby,F  response:: s{8589934621,8589934621,1661429857799,1661429857799,0,22,0,0,19,0,8589934694} 
-------------------------3.判断ACTIVE节点下是否有子节点(主节点)-------------------------
21:41:43.311 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0004, packet:: clientPath:null serverPath:null finished:false header:: 4,8  replyHeader:: 4,8589934698,0  request:: '/cluster_ha/active,F  response:: v{'node01} 
-------------------------3-2.存在子节点(主节点),node02自动创建成为从节点-------------------------
21:41:43.318 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0004, packet:: clientPath:null serverPath:null finished:false header:: 5,1  replyHeader:: 5,8589934699,0  request:: '/cluster_ha/standby/node02,#6e6f64653032,v{s{31,s{'world,'anyone}}},1  response:: '/cluster_ha/standby/node02 
21:41:43.319 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0004, packet:: clientPath:null serverPath:null finished:false header:: 6,8  replyHeader:: 6,8589934699,0  request:: '/cluster_ha/active,T  response:: v{'node01} 
21:41:44.991 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010446d6e0004 after 0ms.
复制代码

启动node03

-------------------------1.创建连接-------------------------
21:13:33.784 [main] INFO org.apache.zookeeper.ZooKeeper - Client environment:zookeeper.version=3.7.0-e3704b390a6697bfdf4b0bef79e3da7a4f6bac4b, built on 2021-03-17 09:46 UTC
21:42:26.606 [main] INFO org.apache.zookeeper.ClientCnxn - zookeeper.request.timeout value is 0. feature enabled=false
-------------------------2.创建PARENT ACTIVE  STANDBY等根节点-------------------------
21:42:26.610 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.SaslServerPrincipal - Canonicalized address to activate.navicat.com
21:42:26.611 [main-SendThread(node01:2181)] INFO org.apache.zookeeper.ClientCnxn - Opening socket connection to server node01/127.0.0.1:2181.
21:42:26.631 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 3,3  replyHeader:: 3,8589934700,0  request:: '/cluster_ha/standby,F  response:: s{8589934621,8589934621,1661429857799,1661429857799,0,23,0,0,19,1,8589934699} 
-------------------------3.判断ACTIVE节点下是否有子节点(主节点)-------------------------
21:42:26.634 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 4,8  replyHeader:: 4,8589934700,0  request:: '/cluster_ha/active,F  response:: v{'node01} 
-------------------------3-2.存在子节点(主节点),node03自动创建成为从节点-------------------------
21:42:26.640 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 5,1  replyHeader:: 5,8589934701,0  request:: '/cluster_ha/standby/node03,#6e6f64653033,v{s{31,s{'world,'anyone}}},1  response:: '/cluster_ha/standby/node03 
21:42:26.641 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 6,8  replyHeader:: 6,8589934701,0  request:: '/cluster_ha/active,T  response:: v{'node01} 
21:42:28.314 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x100104d28f30009 after 0ms.
复制代码

停止node01

node02执行日志

21:43:20.353 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x20010446d6e0004
21:43:20.354 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/cluster_ha/active for session id 0x20010446d6e0004
-------------------------4.ACTIVE根节点下的主节点被删除-------------------------
21:43:20.357 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0004, packet:: clientPath:null serverPath:null finished:false header:: 7,8  replyHeader:: 7,8589934702,0  request:: '/cluster_ha/active,F  response:: v{} 
-------------------------4-1.node02 准备参与竞选-------------------------
21:43:20.357 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0004, packet:: clientPath:null serverPath:null finished:false header:: 8,3  replyHeader:: 8,8589934702,-101  request:: '/cluster_ha/lock,T  response::  
21:43:20.359 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x20010446d6e0004
21:43:20.359 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeCreated path:/cluster_ha/lock for session id 0x20010446d6e0004
21:43:20.360 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0004, packet:: clientPath:null serverPath:null finished:false header:: 9,1  replyHeader:: 9,8589934704,-110  request:: '/cluster_ha/lock,#6e6f64653032,v{s{31,s{'world,'anyone}}},1  response::  
节点: /cluster_ha/lock 创建失败或者节点已经存在
node02 未抢到锁,等待....
21:43:20.373 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0004, packet:: clientPath:null serverPath:null finished:false header:: 10,8  replyHeader:: 10,8589934706,0  request:: '/cluster_ha/active,T  response:: v{'node03} 
-------------------------5.锁被创建-------------------------
21:43:20.375 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x20010446d6e0004, packet:: clientPath:null serverPath:null finished:false header:: 11,4  replyHeader:: 11,8589934706,0  request:: '/cluster_ha/lock,F  response:: #6e6f64653033,s{8589934703,8589934703,1661435000358,1661435000358,0,0,0,72075517623468041,6,0,8589934703} 
-------------------------5-3.当前节点node02未持有锁,放弃任务操作-------------------------
21:43:22.042 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010446d6e0004 after 0ms.
21:43:23.708 [main-SendThread(node02:2182)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x20010446d6e0004 after 0ms.
复制代码

node03执行日志

21:43:20.354 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/cluster_ha/active for session id 0x100104d28f30009
-------------------------4.ACTIVE根节点下的主节点被删除-------------------------
21:43:20.357 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 7,8  replyHeader:: 7,8589934702,0  request:: '/cluster_ha/active,F  response:: v{} 
-------------------------4-1.node03 准备参与竞选-------------------------
21:43:20.357 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 8,3  replyHeader:: 8,8589934702,-101  request:: '/cluster_ha/lock,T  response::  
21:43:20.359 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x100104d28f30009
21:43:20.359 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeCreated path:/cluster_ha/lock for session id 0x100104d28f30009
21:43:20.360 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 9,1  replyHeader:: 9,8589934703,0  request:: '/cluster_ha/lock,#6e6f64653033,v{s{31,s{'world,'anyone}}},1  response:: '/cluster_ha/lock 
21:43:20.360 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 10,8  replyHeader:: 10,8589934704,0  request:: '/cluster_ha/active,T  response:: v{} 
-------------------------5.锁被创建-------------------------
21:43:20.363 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 11,4  replyHeader:: 11,8589934704,0  request:: '/cluster_ha/lock,F  response:: #6e6f64653033,s{8589934703,8589934703,1661435000358,1661435000358,0,0,0,72075517623468041,6,0,8589934703} 
21:43:20.365 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got notification session id: 0x100104d28f30009
21:43:20.365 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/cluster_ha/active for session id 0x100104d28f30009
21:43:20.365 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 12,1  replyHeader:: 12,8589934705,0  request:: '/cluster_ha/active/node03,#6e6f64653033,v{s{31,s{'world,'anyone}}},1  response:: '/cluster_ha/active/node03 
21:43:20.366 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 13,3  replyHeader:: 13,8589934705,0  request:: '/cluster_ha/standby/node03,F  response:: s{8589934701,8589934701,1661434946639,1661434946639,0,0,0,72075517623468041,6,0,8589934701} 
-------------------------5-1.当前节点node03持有锁,切换状态为主节点-------------------------
21:43:20.370 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 14,2  replyHeader:: 14,8589934706,0  request:: '/cluster_ha/standby/node03,-1  response:: null
-------------------------4.ACTIVE根节点下的主节点被删除-------------------------
21:43:20.371 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 15,8  replyHeader:: 15,8589934706,0  request:: '/cluster_ha/active,F  response:: v{'node03} 
-------------------------4-2.ACTIVE根节点下的主节点刚被创建,放弃任何操作-------------------------
21:43:20.372 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply session id: 0x100104d28f30009, packet:: clientPath:null serverPath:null finished:false header:: 16,8  replyHeader:: 16,8589934706,0  request:: '/cluster_ha/active,T  response:: v{'node03} 
21:43:22.040 [main-SendThread(node01:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for session id: 0x100104d28f30009 after 0ms.
复制代码

猜你喜欢

转载自juejin.im/post/7147491217847091208