需求

某分布式系统中,主节点可以有多台,可以动态上下线,任意一台客户端都能实时感知到主节点服务器的上下线。

需求分析

D-ZK服务器动态上下监听 - 图1

具体实现

  1. 先在集群上创建/servers节点

    1. [zk: localhost:2181(CONNECTED) 7] create /servers "servers"
    2. Created /servers
  2. 在Idea中创建包名:com.zh.zhcase1

  3. 服务器端向Zookeeper注册代码 ```java package com.zh.zkcase1;

import org.apache.zookeeper.*;

import java.io.IOException;

/**

  • author: zhanghui
  • project: big-data-learning
  • package: com.zh.zkcase1
  • filename: DistributeServer
  • date: 2022/2/28 14:29
  • description: 服务器端向Zookeeper注册 */ public class DistributeServer { private static String connectString = “linux102:2181,linux103:2181,linux104:2181”; private static int sessionTimeout = 2000; private ZooKeeper zk = null; private String parentNode = “/servers”;

    // 创建到zk的客户端连接 public void getConnect() throws IOException {

     zk = new ZooKeeper(connectString, sessionTimeout, event -> System.out.println(event.getType() + "---" + event.getPath()));
    

    }

    // 注册服务器 public void registerServer(String hostname) throws Exception {

     String create = zk.create(parentNode + "/server", hostname.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
     System.out.println(hostname + " is online " + create);
    

    }

    // 业务功能 public void business(String hostname) throws Exception {

     System.out.println(hostname + " is working...");
     Thread.sleep(Long.MAX_VALUE);
    

    }

    public static void main(String[] args) throws Exception {

     // 1. 获取Zk连接
     DistributeServer server = new DistributeServer();
     server.getConnect();
    
     // 2. 利用Zk连接注册服务器信息
     server.registerServer(args[0]);
    
     // 3. 启动业务功能
     server.business(args[0]);
    

    } } ```

  1. 客户端代码 ```java package com.zh.zkcase1;

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;

/**

  • author: zhanghui
  • project: big-data-learning
  • package: com.zh.zkcase1
  • filename: DistributeClient
  • date: 2022/2/28 14:50
  • description: zk客户端 */ public class DistributeClient { private static String connectString = “linux102:2181,linux103:2181,linux104:2181”; private static int sessionTimeout = 2000; private ZooKeeper zk = null; private String parentNode = “/servers”;

    // 创建到zk的客户端连接 public void getConnect() throws IOException {

     new ZooKeeper(connectString, sessionTimeout, event -> {
         System.out.println(event.getType() + "---" + event.getPath());
    
         // 再次启动监听
         try {
             getServerList();
         } catch (Exception e) {
             e.printStackTrace();
         }
     });
    

    }

    // 获取服务器列表信息 public void getServerList() throws Exception {

     // 1. 获取服务器子节点信息,并且对父节点进行监听
     List<String> children = zk.getChildren(parentNode, true);
    
     // 2. 存储服务器信息列表
     ArrayList<String> servers = new ArrayList<>();
    
     // 3. 遍历所有节点,获取节点中的主机名称信息
     for (String child : children) {
         byte[] data = zk.getData(parentNode + "/" + child, false, null);
         servers.add(new String(data));
     }
    
     // 4. 打印服务器列表信息
     System.out.println(servers);
    

    }

    // 业务功能 public void business() throws Exception {

     System.out.println("client is working...");
     Thread.sleep(Long.MAX_VALUE);
    

    }

    public static void main(String[] args) throws Exception {

     // 1. 获取ZK连接
     DistributeClient client = new DistributeClient();
     client.getConnect();
    
     // 2. 获取servers的子节点信息,从中获取服务器信息列表
     client.getServerList();
    
     // 3. 业务进程启动
     client.business();
    

    } } ```

测试

  1. 在linux命令行上操作增加减少服务器

    1. 启动DistributeClient客户端
    2. 在linux102上ZK的客户端/servers目录上创建临时带序号节点

      [zk: localhost:2181(CONNECTED) 8] create -e -s /servers/linux102 "linux102"
      Created /servers/linux1020000000000
      [zk: localhost:2181(CONNECTED) 9] create -e -s /servers/linux103 "linux103"
      Created /servers/linux1030000000001
      
    3. 观察idea控制台

      NodeChildrenChanged---/servers
      [linux102, linux103]
      
    4. 执行删除操作

      [zk: localhost:2181(CONNECTED) 10] delete /servers/linux1020000000000
      
    5. 观察idea控制台变化

      NodeChildrenChanged---/servers
      [linux103]
      
  2. 在IDEA上操作增加减少服务器

    1. 启动DistributeClient客户端(如果已经启动过,不需要启动)
    2. 启动DistributeServer服务
      1. 点击Edit Configurations…

image.png

  2. 在弹出的窗口中(Program arguments)输入想启动的主机,例如,linux102

image.png

  3. 回到DistributeServer的main方法,右键,在弹出的窗口中点击`Run "DistributeServer.main()"`

  4. 观察DistributeServer控制台,提示`linux102 is working...`
  4. 观察DistributeClient控制台,提示`[linux102, linux103]`