这是因为连接尚未成功建立,就操作节点。
当你 new Zookeeper 时,由于 zookeeper 的连接是异步的,导致 zookeeper 尚未正确连接,操作节点的代码就会执行。
解决方法如下:使用 CountDownLatch
public class Client01 {
private String connectString = "192.168.1.131:2181,192.168.1.132:2181,192.168.1.133:2181";
private int sessionTimeOut = 30000; // 超时时间,注意,时间最好设长一点,zookeeper连接很慢
private ZooKeeper zooKeeper;
private CountDownLatch countDownLatch;
public void init() throws IOException {
countDownLatch = new CountDownLatch(1);
zooKeeper = new ZooKeeper(connectString, sessionTimeOut, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getState() == Event.KeeperState.SyncConnected) {
countDownLatch.countDown(); // 计数器减一
System.out.println("-----连接已建立-----");
}
}
});
waitUntilConnected(zooKeeper,countDownLatch);
}
public void waitUntilConnected(ZooKeeper zooKeeper, CountDownLatch connectedLatch) {
if (ZooKeeper.States.CONNECTING == zooKeeper.getState()) {
try {
System.out.println("正在连接...."+zooKeeper.getState());
connectedLatch.await(); // 没有 countDown,则 await 之后代码不会执行,但之前的代码会执行
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
@Test
public void testCreate() throws InterruptedException, KeeperException, IOException {
init();
// 创建节点,参数:节点路径,数据值,权限(任何人都能访问),节点的类型(持久)
String str = zooKeeper.create("/person","asia".getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(str);
}
}
你只需要把 ip 地址该一下就行。
思路:
- 在 zookeeper 的 状态尚未是 connected 的时候,就阻塞,不执行 节点操作, 直到 connected 时, countDown 使计数器减一,await 后的代码就得以执行