通过JAVA API,实验两个客户端对同一Zookeeper服务znode节点的监听并传递消息(既能监听又能修改节点的值)

可以通过原生的java API实现这个需求,但是实现过程较为麻烦,所以选用curator框架。

如果你的zookeeper集群搭建在不同的虚拟机上,则只需要在本地的idea上运行下面的代码即可;如果你是和我一样,用docker搭建的zookeeper集群,则需要在虚拟机主机上下载idea,然后运行下面的代码。

环境准备:开启zookeeper集群,下载idea,新建maven项目(springboot项目也行,优点是:可以将curator的配置参数交给spring管理,一个类里面只需自动注入一次便能使用,缺点:每次启动太慢太麻烦了)。

1、在pom.xml文件中导入依赖

<dependencies>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.10</version>
        </dependency>

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

    </dependencies>

2、在resources目录下建log4j.properties文件,内容如下:

log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

3、建一个测试类,内容如下:

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.junit.Test;

import java.nio.charset.StandardCharsets;
import java.util.Scanner;


public class myZookeepertest {

    @Test
    public void createNode() throws Exception {
        String connectString = "hadoop1:2181"; // 设置要监听的ip和端口号
        int sessionTimeoutMs = 20000;
        int connectionTimeoutMs = 5000;
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 1);
        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(connectString, sessionTimeoutMs, connectionTimeoutMs, retryPolicy);
        curatorFramework.start();
        //添加持久节点
        String Znode = curatorFramework.create().forPath("/zookeeper/test","zookeepertest".getBytes());
        //添加临时序号节点
//        String path1 = curatorFramework.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/zookeeper/test", "some-data".getBytes());
        System.out.println(String.format("curator create node :%s  successfully.",Znode));

        System.in.read();

    }
    
    @Test
    public void addNodeListener() throws Exception {
        String connectString = "hadoop1:2181";
        int sessionTimeoutMs = 20000;
        int connectionTimeoutMs = 5000;
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 1);
        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(connectString, sessionTimeoutMs, connectionTimeoutMs, retryPolicy);
        curatorFramework.start();
        NodeCache nodeCache = new NodeCache(curatorFramework, "/zookeeper/test");
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
//        log.info("{} path nodeChanged: ","/zookeeper/test");
                byte[] bytes = curatorFramework.getData().forPath("/zookeeper/test");
                System.out.println(new String(bytes));
            }
        });

        nodeCache.start();
        Scanner scanner = new Scanner(System.in);
        String in = null;
        while(true){
            in = scanner.nextLine();
            if(in.equals("stop")) break; // 如果输入stop,则只监听,不传递消息
            curatorFramework.setData().forPath("/zookeeper/test",("huangpili: " + in).getBytes());
        }
        System.in.read();

    }

    @Test
    public void addNodeListener1() throws Exception {
        String connectString = "hadoop1:2181";
        int sessionTimeoutMs = 20000;
        int connectionTimeoutMs = 5000;
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(5000, 5);
        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(connectString, sessionTimeoutMs, connectionTimeoutMs, retryPolicy);
        curatorFramework.start();
        NodeCache nodeCache = new NodeCache(curatorFramework, "/zookeeper/test");
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                byte[] bytes = curatorFramework.getData().forPath("/zookeeper/test");
                System.out.println(new String(bytes));
            }
        });

        nodeCache.start();
        Scanner scanner = new Scanner(System.in);
        String in = null;
        while(true){
            in = scanner.nextLine();
            if(in.equals("stop")) break;
            curatorFramework.setData().forPath("/zookeeper/test",("lufei: " + in).getBytes());
        }
        System.in.read();

    }

}

4、测试代码(一定要换成你自己要监听的ip地址和端口号

(1)创建节点:运行createNode()方法,运行结果如下所示:

 (2)开启两个客户端,分别运行addNodeListener()和addNodeListener1()方法

在控制台中输入任意字符串(两个客户端都可以输入)实现两个客户端之间传递消息,运行结果如下所示:

 

 5、控制台无法输入

如果你的控制台无法输入,是idea的问题,解决方法如下所示:

 

添加:

-Deditable.java.test.console=true

然后重启idea就行了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值