【大数据】Zookeeper的Java API应用

这里简单模拟了一个分布式应用的主节点HA及客户端动态更新主节点状态的场景。以便于了解Zookeeper的java API。


场景:三台服务器mini1,mini2,mini3,上线后向Zookeeper注册信息,然后客户端实时获取服务器列表。


代码中将服务器注册在Zookeeper的“/servers”路径下,需要先创建这个路径,方法为:
1.在Zookeeper服务端输入zkCli.sh(前提得先将Zookeeper启动,具体方法见【大数据】Zookeeper的学习与安装(附加脚本全启动)
这里写图片描述
2.关于Zookeeper的命令,可以通过-help查看了解,这里就不多说了,输入create /servers iii即可(这里create后面第一个参数是指创建节点名称,第二个参数是指节点内容,这里随便写为iii)
这里写图片描述

服务器端:

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
public class DistributedServer {
    //设置连接路径(我的三台Zookeeper服务器)
    private static final String connectString = "zkmini1:2181,zkmini2:2181,zkmini3:2181";
    //设置超时时间
    private static final int sessionTimeout = 2000;
    //父节点路径
    private static final String parentNodePath = "/servers";
    private static ZooKeeper zk = null;
    //获取Zookeeper连接
    public void getConnection() throws Exception{
        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override 
            public void process(WatchedEvent event) {
                //打印监听器事件即发生路径
                System.out.println("触发事件:" + event.getType() + "&&触发路径:" + event.getPath());
                try {
                    //重新绑定监听器
                    zk.getChildren("/", true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    //注册服务器到Zookeeper上
    public void registerServer(String hostname) throws Exception{
        //在Zookeeper上创建服务器信息节点
        //parm1:节点路径
        //parm2:节点内容,这里就可以写服务器信息,例如服务器名、ip等信息,可传任何形式参数,byte流。
        //parm3:节点的acl策略
        //parm4:节点类型,类型定义在枚举CreateMode中:(1)PERSISTENT:持久;(2)PERSISTENT_SEQUENTIAL:持久顺序;(3)EPHEMERAL:临时;(4)EPHEMERAL_SEQUENTIAL:临时顺序。
        zk.create(parentNodePath + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println(hostname + " is Online.");
    }
    //模拟服务期间的业务逻辑
    public void hanlerBussiness(String hostname) throws Exception{
        System.out.println(hostname + " start working...");
        Thread.sleep(Long.MAX_VALUE);

    }
    //模拟传入参数:服务器名
    public static void main(String[] args) throws Exception {
        DistributedServer ds = new DistributedServer();
        //获取zk连接
        ds.getConnection();
        //利用zk连接注册服务器信息
        ds.registerServer(args[0]);
        //处理业务逻辑
        ds.hanlerBussiness(args[0]);
    }
}

测试运行截图
这里写图片描述


客户端

客户端主要事实获取服务器列表,当服务器上下线时,客户端均可以感知,并再次获取服务器列表。

import java.util.ArrayList;
import java.util.List;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

public class DistributedClient {
    //设置连接路径(我的三台Zookeeper服务器)
    private static final String connectString = "zkmini1:2181,zkmini2:2181,zkmini3:2181";
    //设置超时时间
    private static final int sessionTimeout = 2000;
    //父节点路径
    private static final String parentNodePath = "/servers";
    public volatile List<String> serverList= new ArrayList<>();
    private static ZooKeeper zk = null;

    public void getConnection() throws Exception{
        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override 
            public void process(WatchedEvent event) {
                System.out.println("触发事件:" + event.getType() + "&&触发路径:" + event.getPath());
                try {
                    //重新更新服务器列表并绑定监听。
                    getServerList();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    /**
     * 获取服务器信息列表
     * @throws Exception
     */
    public void getServerList() throws Exception{
        //获取服务器子节点信息,并对其父节点进行监听
        List<String> children = zk.getChildren(parentNodePath, true);
        //先创建一个临时的list来存服务器列表信息
        List<String> sl = new ArrayList<>();
        for(String child : children){
            String data = new String(zk.getData(parentNodePath+"/" + child, false, null));
            sl.add(data);
        }
        System.out.println(serverList);
        serverList = sl;
    }
    //模拟客户端的业务逻辑
    public void hanlerBussiness() throws Exception{
        System.out.println(" clinet start working...");
        Thread.sleep(Long.MAX_VALUE);

    }
    public static void main(String[] args) throws Exception {
        DistributedClient dc = new DistributedClient();
        //获取zk连接
        dc.getConnection();
        //获取服务器列表
        dc.getServerList();
        //业务逻辑
        dc.hanlerBussiness();
    }
}

测试运行截图:
这里写图片描述


然后将这两个文件打包,就可以正式模拟场景运行了:(一个cmd窗口模拟一台服务器,下面均在不同cmd窗口,客户端在eclipse上运行)
1.先启动mini1、mini2:
这里写图片描述
这里写图片描述
2.启动客户端:(这图其实是最先启动客户端,再启动mini1,mini2)
这里写图片描述
可以看到现在有两台服务器为[mini1,mini2]
3.启动第三台服务器:
这里写图片描述
客户端出现:
这里写图片描述


这样就OK拉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值