可以通过原生的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就行了。