目录
一、案例需求
- 在分布式系统中,主节点可以有多台,可以动态上下线,任意一台客户端都能实时感知到主节点服务器的上下线。
二、案例需求分析
-
服务端启动时去注册信息(创建都是临时节点)。
-
获取到当前在线服务器列表,并且注册监听。
-
服务器节点下线。
-
服务器节点上下线事件通知。
-
重新再去获取服务器列表,并注册监听。
三、案例具体代码实现
3.1、在集群上创建 servers 节点
-
创建 servers 节点
[zk: localhost:2181(CONNECTED) 2] create /servers "servers"
3.2、服务器端向 Zookeeper 注册代码
-
服务注册器
package com.xz.case1; import org.apache.zookeeper.*; import java.io.IOException; public class DistributeServer { private String connectString = "192.168.136.27:2181,192.168.136.28:2181,192.168.136.29:2181"; private int sessionTimeout = 200000; private ZooKeeper zk; public static void main(String[] args) throws IOException, KeeperException, InterruptedException { DistributeServer server = new DistributeServer(); // 1 获取zk连接 server.getConnect(); // 2 注册服务器到zk集群 server.regist("192.168.136.27"); // 3 启动业务逻辑 server.business(); } /** * 3、启动业务逻辑 * */ private void business() throws InterruptedException { Thread.sleep(Long.MAX_VALUE); } /** * 2、注册服务器到zk集群 * */ private void regist(String hostname) throws KeeperException, InterruptedException { String create = zk.create("/servers/"+hostname, hostname.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); System.out.println(hostname +" is online") ; } /** * 1、获取zk连接 * */ private void getConnect() throws IOException { zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { } }); } }
3.3、客户端监听代码
-
客户端监听代码
package com.xz.case1; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class DistributeClient { private String connectString = "192.168.136.27:2181,192.168.136.28:2181,192.168.136.29:2181"; private int sessionTimeout = 200000; private ZooKeeper zk; public static void main(String[] args) throws IOException, KeeperException, InterruptedException { DistributeClient client = new DistributeClient(); // 1 获取zk连接 client.getConnect(); // 2 监听/servers下面子节点的增加和删除 client.getServerList(); // 3 业务逻辑 client.business(); } private void business() throws InterruptedException { Thread.sleep(Long.MAX_VALUE); } /** * 2 监听/servers下面子节点的增加和删除 * */ private void getServerList() throws KeeperException, InterruptedException { //监听路径 servers List<String> children = zk.getChildren("/servers", true); ArrayList<String> servers = new ArrayList<>(); //遍历路径 servers下的所有节点 for (String child : children) { byte[] data = zk.getData("/servers/" + child, false, null); servers.add(new String(data)); } // 打印 System.out.println(servers); } /** * 1、获取zk连接 * */ private void getConnect() throws IOException { zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { try { getServerList(); } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }); } }
四、测试
4.1、在 Linux 命令行上操作增加减少服务器
-
启动 DistributeClient 客户端
-
在 192.168.136.27服务器上 zk 的客户端/servers 目录上创建临时带序号节点
[zk: localhost:2181(CONNECTED) 3] create -e -s /servers/192.168.136.28 "28" [zk: localhost:2181(CONNECTED) 4] create -e -s /servers/192.168.136.29 "29"
-
观察 Idea 控制台变化
-
执行删除操作
[zk: localhost:2181(CONNECTED) 5] delete /servers/192.168.136.280000000000
-
观察 Idea 控制台变化
4.2、在 Idea 上操作增加减少服务器
- 启动 DistributeClient 客户端(如果已经启动过,不需要重启)
- 启动 DistributeServer 服务,观察 DistributeServer 控制台,提示 192.168.136.27服务 is working