zookeeper的Java API模拟服务注册与发现

构建服务提供者

构建server1
/**
 *  返回唯一的zookeeper实例
 * @author sheledon
 */
public class ZkFactory {
    private static final int sessionTimeout = 7000;
    private static volatile ZooKeeper zkClient;
    private static String serverAddress = "ip1:port1,ip2:port2";

    private ZkFactory() throws IOException { }

    public static ZooKeeper getZkClientInstance() throws IOException {
        if (zkClient==null){
            synchronized (ZkFactory.class){
                if (zkClient==null){
                    zkClient = new ZooKeeper(serverAddress,sessionTimeout,null);
                }
            }
        }
        return zkClient;
    }
}
/**
 * 模拟分布式系统中服务注册
 * 使用zookeeper作为服务的注册中心
 * @author sheledon
 */
public class Main {
    private static CountDownLatch latch = new CountDownLatch(1);
    public static void main(String[] args) throws InterruptedException, IOException, KeeperException {
        Main main = new Main();
        main.registerService();
        main.provideService();
        latch.await();
    }
    //服务注册
    private void registerService() throws IOException, KeeperException, InterruptedException {
        ZooKeeper zooKeeper = ZkFactory.getZkClientInstance();
        String address = "127.0.0.1:8081";
        String znodePath = "/service-list/service1";
        zooKeeper.create(
                znodePath,
                address.getBytes(StandardCharsets.UTF_8),
                ZooDefs.Ids.OPEN_ACL_UNSAFE,
                CreateMode.EPHEMERAL,
                new AsyncCallback.StringCallback() {
                    @Override
                    public void processResult(int rc, String path, Object ctx, String name) {
                        System.out.println("注册状态: "+rc);
                        System.out.println("服务注册: "+path);
                    }
                },null);
    }
    // socket 通信
    private void provideService() throws IOException {
        ServerSocket serverSocket = new ServerSocket(8081);
        while (true){
            Socket socket = serverSocket.accept();
            System.out.println("client ip: "+socket.getInetAddress().getHostAddress());
            System.out.println("client port: "+socket.getPort());
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try(OutputStream ops = socket.getOutputStream()){
                        ops.write("port is 8081 提供服务".getBytes(StandardCharsets.UTF_8));
                        ops.flush();
                    }catch (Exception e){
                        System.out.println(e);
                    }
                }
            }).start();
        }
    }
}
复制一份创建 server2

创建服务消费者

/**
 *  获取服务列表的线程
 * @author sheledon
 */
public class ZkService extends Thread{

    //服务列表
    private volatile String [] services;
    private String basePath = "/service-list";
    private static final int sessionTimeout = 7000;
    private static volatile ZooKeeper zkClient;
    private static String serverAddress = "39.104.84.176:2181,39.104.84.176:2182,39.104.84.176:2183";
    private static CountDownLatch latch = new CountDownLatch(1);
    public ZkService() throws IOException {
        zkClient = new ZooKeeper(serverAddress,sessionTimeout,new WatcherImpl());
    }

    @Override
    public void run() {
        try {
            getServiceListFromZK();
            latch.await();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public String[] getServices(){
        return this.services;
    }
    private void getServiceListFromZK() throws IOException, KeeperException, InterruptedException {
        zkClient.getChildren(basePath,true,new IChildrenCallback(),"");
    }
    private void getServiceAddress(List<String> serviceList) throws KeeperException, InterruptedException {
        int n = serviceList.size();
        if (n==0){
            return ;
        }
        System.out.println("更新服务列表");
        this.services = new String[n];
        for (int i=0;i<n;++i){
            byte[] data = zkClient.getData(basePath + "/" + serviceList.get(i), false, new Stat());
            services[i] = new String(data, Charset.forName("utf-8"));
            System.out.println(services[i]);
        }
    }

    /**
     * 获得子节点的异步回调
     */
    private class IChildrenCallback implements AsyncCallback.ChildrenCallback{
        @Override
        public void processResult(int rc, String path, Object ctx, List<String> children) {
            if (rc==0){
                try {
                    getServiceAddress(children);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 子节点列表发生改变的监听回调
     */
    private class WatcherImpl implements Watcher{
        @Override
        public void process(WatchedEvent event) {
            if (Event.EventType.NodeChildrenChanged == event.getType()) {
                zkClient.getChildren(event.getPath(),true,new IChildrenCallback(),null);
            }
        }
    }
}

Main
/**
 * 使用循环模拟从 zookeeper 中获得服务列表,然后挑选服务发起访问
 */
public class Main {
    private static Socket socket ;
    private static String [] services;
    public static void main(String[] args) throws IOException, InterruptedException {
        ZkService zkService = new ZkService();
        zkService.start();
        Thread.sleep(2000);
        Random random = new Random(100);
        //每三秒获得一次服务列表
        while (true){
            String [] newServices = zkService.getServices();
            if (newServices!=null){
                services=newServices;
            }
            if (services==null){
                continue;
            }
            int i = random.nextInt(services.length);
            String[] address = services[i].split(":");
            socket=new Socket();
            try {
                socket.connect(new InetSocketAddress(address[0],Integer.parseInt(address[1])));
            }catch (Exception e){
                System.out.println(e);
                continue;
            }
            InputStream inputStream = socket.getInputStream();
            byte [] bs = new byte[1024];
            inputStream.read(bs);
            System.out.println(new String(bs, Charset.forName("utf-8")));
            Thread.sleep(3000);
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值