模拟zookeeper动态上下线

原理就是客户端连接到ZooKeeper集群后,一直监听一个节点,然后服务器连接到Zookeeper集群后,在客户端监听的节点下创建一个代表自身信息的临时节点,这样客户端就可以收到服务器的上下线消息了。

为了您的观看体验,下面的代码需要您有以下前置知识:

  1. 了解ZooKeeper相关知识及其常用命令;
  2. 了解Java的ZooKeeper API;

首先创建一个共有的父类AbstractZooKeeper

public abstract class AbstractZooKeeper {

    //zookeeper集群的服务器地址和端口
    private final String CLUSTER = "此处应为你自己的服务器集群对应IP和端口";
    //客户端会话超时时间,毫秒
    private final int SESSION_TIMEOUT = 2000;
    protected ZooKeeper zooKeeper;

    public AbstractZooKeeper() {
        init(); //初始化zookeeper客户端
    }

    private void init() {
        try {
            zooKeeper = new ZooKeeper(CLUSTER, SESSION_TIMEOUT, (watchedEvent) -> {
                watcher();
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 监视器,留给子类实现
     */
    public abstract void watcher();

}

然后写一个客户端继承它:

public class ZKClient extends AbstractZooKeeper {

    @Override
    public void watcher() {
        try {
            getServer(); //重写父类的watcher方法,实现自己的逻辑
        } catch (InterruptedException | KeeperException e) {
            e.printStackTrace();
        }
    }

    /**
     * 监听/servers节点的变化
     */
    public void getServer() throws InterruptedException, KeeperException {
        List<String> children = zooKeeper.getChildren("/servers", true);
        System.out.println(children);
    }

    //模拟客户端运行,直接睡就好
    public void business() {
        try {
            Thread.sleep(Long.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

接着就是服务端,同样继承它:

public class ZKServer extends AbstractZooKeeper {

    private String serverName; //服务名
    private String hostname; //主机名
    private Integer port; //端口号

    public ZKServer(String serverName, String hostname, Integer port) {
        this.serverName = serverName;
        this.hostname = hostname;
        this.port = port;
    }

    /**
     * 将server注册到该/servers节点下,使用临时节点并且编号的节点
     */
    public void register() throws InterruptedException, KeeperException {
        String path = zooKeeper.create("/servers/" + serverName,
                (hostname + port).getBytes(StandardCharsets.UTF_8),
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println(serverName + " is online, zookeeper real path is " + path);
    }

    //模拟客户端运行,直接睡就好
    public void business() {
        try {
            Thread.sleep(Long.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void watcher() {
		//自己的监视逻辑,有需要再自行实现
    }
}

接着就是我们的测试类了:

public class ZKDynamicOnlineAndOffline {

    @Test
    public void client() {
        ZKClient zkClient = new ZKClient();
        zkClient.business();
    }

    @Test
    public void server1() throws InterruptedException, KeeperException {
        ZKServer zkServer = new ZKServer("order", "17.142.153.3", 8080);
        zkServer.register();
        zkServer.business();
    }

    @Test
    public void server2() throws InterruptedException, KeeperException {
        ZKServer zkServer = new ZKServer("order", "17.142.153.4", 8080);
        zkServer.register();
        zkServer.business();
    }

    @Test
    public void server3() throws InterruptedException, KeeperException {
        ZKServer zkServer = new ZKServer("order", "17.142.153.5", 8080);
        zkServer.register();
        zkServer.business();
    }
}

代码供参考阅读,有兴趣的小伙伴可以复制运行看下效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值