zookeeper03

1 zookeeper开源客户端curator介绍

1.1 curator简介

  • curator是Netflix公司开源的一个zookeeper客户端,后来捐赠给Apache。curator框架在zookeeper原生API接口上进行了包装,解决了很多zookeeper客户端非常底层的细节开发。提供zookeeper各种应用场景(比如:分布式锁服务、集群领导选举、共享计数器、缓存机制、分布式队列等)的抽象封装,实现了Fluent风格的API接口,是最好用,最流行的zookeeper的客户端。

  • 原生zookeeperAPI的不足:

    • 1️⃣连接对象异步创建,需要开发人员自行编码等待。
    • 2️⃣连接没有自动重连超时机制。
    • 3️⃣watcher一次注册生效一次。
    • 4️⃣不支持递归创建树形节点。
  • curator的特点:

    • 1️⃣解决了session会话超时重连。
    • 2️⃣watcher反复注册。
    • 3️⃣简化开发API。
    • 4️⃣遵循Fluent风格的API。
    • 5️⃣提供了分布式锁服务,共享计数器、缓存机制等解决方案。
  • maven依赖:

<!-- 需要和zookeeper的安装版本保持一致 -->
<!-- 对zookeeper的底层api的一些封装 -->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.12.0</version>
</dependency>
<!-- 封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等 -->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.12.0</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
</dependency>

1.2 连接到zookeeper

  • 示例:
package com.sunxiaping.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryOneTime;

public class ZookeeperConnection {
    public static void main(String[] args) {
        CuratorFramework client = CuratorFrameworkFactory.builder()
                //连接参数
                .connectString("192.168.40.101:2181")
                //会话超时时间
                .sessionTimeoutMs(5000)
//                .namespace("hadoop")
                //重试机制
                .retryPolicy(new RetryOneTime(3000))
                .build();
        //开始连接
        client.start();
        System.out.println("client.isStarted() = " + client.isStarted());
        //关闭连接
        client.close();
        System.out.println("client.isStarted() = " + client.isStarted());

    }
}

1.3 curator连接对象的重连策略

  • 示例:
package com.sunxiaping.curator;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.retry.RetryNTimes;
import org.apache.curator.retry.RetryOneTime;
import org.apache.curator.retry.RetryUntilElapsed;

/**
 * 连接到zookeeper
 */
public class CuratorConnection {
    public static void main(String[] args) {
        //IP地址端口号
        String connectString = "192.168.179.101:2181,192.168.179.102:2181,192.168.179.103:2181";
        //会话超时时间
        int sessionTimeoutMs = 5000;
        //重试策略
        //① 3秒后重连,只重连一次
        RetryPolicy retryPolicy = new RetryOneTime(3000);
        //② 每3秒重连一次,重连3次
        retryPolicy = new RetryNTimes(3, 3000);
        //③ 每3秒重连一次,总等待时间超过10秒后停止重连
        retryPolicy = new RetryUntilElapsed(10000, 3000);
        //④ baseSleepTimeMs* Math.max(1,random.nextInt(1 << (retryCount +1)))
        retryPolicy = new ExponentialBackoffRetry(1000, 3);

        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString(connectString)
                .sessionTimeoutMs(sessionTimeoutMs)
                .retryPolicy(retryPolicy)
                //命名空间 以命名空间指定的字符串作为“/命名空间”节点查询
//                .namespace("create")
                .build();
        //打开连接
        client.start();
        System.out.println("连接是否打开 = " + client.isStarted());
        //关闭连接
        client.close();
    }
}

1.4 新增节点

  • 示例:
package com.sunxiaping.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.junit.Before;
import org.junit.Test;

/**
 * curator创建节点
 */
public class CreateNode {

    private CuratorFramework client;

    @Before
    public void before() {
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.40.101:2181")
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("hadoop")
                .build();
        client.start();
    }

    @Test
    public void after() {
        if (client != null) {
            client.close();
        }
    }

    @Test
    public void testCreateNode1() throws Exception {
        String path = client.create()
                //持久节点
                .withMode(CreateMode.PERSISTENT)
                //ACL
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                //节点路径和节点数据
                .forPath("/node1", "node1".getBytes());
        System.out.println("path = " + path);
    }

    /**
     * 递归创建节点
     *
     * @throws Exception
     */
    @Test
    public void testCreateNode2() throws Exception {
        String path = client.create()
                //递归创建
                .creatingParentContainersIfNeeded()
                //持久节点
                .withMode(CreateMode.PERSISTENT)
                //ACL
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                //节点路径和节点数据
                .forPath("/node2/node21", "node21".getBytes());
        System.out.println("path = " + path);
    }

    /**
     * 异步方式创建节点
     *
     * @throws Exception
     */
    @Test
    public void testCreateNode3() throws Exception {
        client.create()
                //递归创建
                .creatingParentContainersIfNeeded()
                //持久节点
                .withMode(CreateMode.PERSISTENT)
                //ACL
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                //异步回调接口
                .inBackground(new BackgroundCallback() {
                    @Override
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent event) throws Exception {
                        System.out.println("节点路径 = " + event.getPath());
                        System.out.println("事件类型 = " + event.getType());
                    }
                })
                //节点路径和节点数据
                .forPath("/node3/node31", "node31".getBytes());

        Thread.sleep(5000);
        System.out.println("结束");
    }

}

1.5 更新节点

  • 示例:
package com.sunxiaping.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

/**
 * 更新节点
 */
public class UpdateNode {
    private CuratorFramework client;

    @Before
    public void before() {
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.40.101:2181")
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("hadoop")
                .build();
        client.start();
    }

    @Test
    public void after() {
        if (client != null) {
            client.close();
        }
    }

    @Test
    public void testUpdateNode() throws Exception {
        Stat stat = client.setData().withVersion(-1).forPath("/node1", "node1 update".getBytes());
        System.out.println("stat = " + stat);
    }

    @Test
    public void testUpdateNode2() throws Exception {
        client.setData().withVersion(-1)
                 .inBackground(new BackgroundCallback() {
                     @Override
                     public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                         System.out.println("节点路径 = " + event.getPath());
                         System.out.println("事件类型 = " + event.getType());
                     }
                 })
                .forPath("/node1", "node11 update".getBytes());

        Thread.sleep(5000);
        System.out.println("结束");
    }
}

1.6 删除节点

  • 示例:
package com.sunxiaping.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.Before;
import org.junit.Test;

/**
 * 删除节点
 */
public class DeleteNode {
    private CuratorFramework client;

    @Before
    public void before() {
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.40.101:2181")
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("hadoop")
                .build();
        client.start();
    }

    @Test
    public void after() {
        if (client != null) {
            client.close();
        }
    }

    /**
     * 删除节点
     *
     * @throws Exception
     */
    @Test
    public void testDeleteNode() throws Exception {
        client.delete().withVersion(-1).forPath("/node1");
    }

    /**
     * 递归删除
     *
     * @throws Exception
     */
    @Test
    public void testDeleteNode2() throws Exception {
        client.delete()
                //递归删除
                .deletingChildrenIfNeeded()
                .withVersion(-1)
                .forPath("/node2");
    }


    /**
     * 异步删除
     *
     * @throws Exception
     */
    @Test
    public void testDeleteNode3() throws Exception {
        client.delete()
                //递归删除
                .deletingChildrenIfNeeded()
                .withVersion(-1)
                .inBackground(new BackgroundCallback() {
                    @Override
                    public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                        System.out.println("节点路径 = " + event.getPath());
                        System.out.println("事件类型 = " + event.getType());
                    }
                })
                .forPath("/node3");
        Thread.sleep(5000);
        System.out.println("结束");
    }

}

1.7 查看节点数据

  • 示例:
package com.sunxiaping.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

/**
 * 查看节点数据
 */
public class GetNodeData {
    private CuratorFramework client;

    @Before
    public void before() {
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.40.101:2181")
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("hadoop")
                .build();
        client.start();
    }

    @Test
    public void after() {
        if (client != null) {
            client.close();
        }
    }

    /**
     * 读取节点数据
     *
     * @throws Exception
     */
    @Test
    public void testGetNodeData1() throws Exception {
        byte[] bytes = client.getData().forPath("/node1");
        System.out.println("data = " + new String(bytes));
    }


    /**
     * 读取节点数据时获取节点的属性
     *
     * @throws Exception
     */
    @Test
    public void testGetNodeData2() throws Exception {
        Stat stat = new Stat();
        byte[] bytes = client.getData().storingStatIn(stat).forPath("/node1");
        System.out.println("data = " + new String(bytes));
        System.out.println("stat = " + stat);
    }

    /**
     * 异步方式读取节点数据
     *
     * @throws Exception
     */
    @Test
    public void testGetNodeData3() throws Exception {
        client.getData().inBackground(new BackgroundCallback() {
            @Override
            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                System.out.println("节点路径 = " + event.getPath());
                System.out.println("事件类型 = " + event.getType());

                System.out.println("结果 = " + new String(event.getData()));
            }
        }).forPath("/node1");

        Thread.sleep(5000);
        System.out.println("结束");
    }


}

1.8 查看子节点数据

  • 示例:
package com.sunxiaping.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

/**
 * 查看节点数据
 */
public class GetChildrenNodeData {
    private CuratorFramework client;

    @Before
    public void before() {
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.40.101:2181")
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("hadoop")
                .build();
        client.start();
    }

    @Test
    public void after() {
        if (client != null) {
            client.close();
        }
    }

    /**
     * 读取子节点数据
     *
     * @throws Exception
     */
    @Test
    public void GetChildrenNodeData1() throws Exception {
        List<String> list = client.getChildren().forPath("/node1");
        System.out.println("list = " + list);
    }


    /**
     * 读取子节点数据时获取节点的属性
     *
     * @throws Exception
     */
    @Test
    public void testGetNodeData2() throws Exception {
        Stat stat = new Stat();
        List<String> list = client.getChildren().storingStatIn(stat).forPath("/node1");
        System.out.println("list = " + list);
        System.out.println("stat = " + stat);
    }

    /**
     * 异步方式读取子节点数据
     *
     * @throws Exception
     */
    @Test
    public void testGetNodeData3() throws Exception {
        client.getChildren().inBackground(new BackgroundCallback() {
            @Override
            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                System.out.println("节点路径 = " + event.getPath());
                System.out.println("事件类型 = " + event.getType());
                List<String> list = event.getChildren();
                System.out.println("list = " + list);
                Stat stat = event.getStat();
                System.out.println("stat = " + stat);
            }
        }).forPath("/node1");

        Thread.sleep(5000);
        System.out.println("结束");
    }

}

1.9 查看节点是否存在

  • 示例:
package com.sunxiaping.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

public class ExistsNode {
    private CuratorFramework client;

    @Before
    public void before() {
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.40.101:2181")
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("hadoop")
                .build();
        client.start();
    }

    @Test
    public void after() {
        if (client != null) {
            client.close();
        }
    }

    @Test
    public void testExistsNode1() throws Exception {
        Stat stat = client.checkExists().forPath("/node1");
        System.out.println("stat = " + stat);
    }

    @Test
    public void testExistsNode2() throws Exception {
        client.checkExists()
                .inBackground(new BackgroundCallback() {
                    @Override
                    public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                        System.out.println("节点路径 = " + event.getPath());
                        System.out.println("事件类型 = " + event.getType());

                        Stat stat = event.getStat();
                        System.out.println("stat = " + stat);
                    }
                }).forPath("/node1");
        Thread.sleep(5000);
        System.out.println("结束");
    }

}

1.10 事件监听机制

  • curator提供了两种Watcher(Cache)来监听节点的变化。

  • Node Cache:只是监听某一个特定的节点,监听节点的新增和修改。

  • PathChildren Cache:监控一个znode节点,当一个子节点增加、删除时,PathChildren Cache会改变它的状态,会包含最新的子节点,子节点数据和状态。

  • 示例:

package com.sunxiaping.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.Before;
import org.junit.Test;

public class CuratorWatcher {
    private CuratorFramework client;

    @Before
    public void before() {
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.40.101:2181")
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("hadoop")
                .build();
        client.start();
    }

    @Test
    public void after() {
        if (client != null) {
            client.close();
        }
    }

    @Test
    public void testWatcher1() throws Exception {
        //监视某个节点数据的变化
        NodeCache nodeCache = new NodeCache(client, "/watcher1");
        //增加监听器
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            //当节点变化时
            @Override
            public void nodeChanged() throws Exception {
                String path = nodeCache.getCurrentData().getPath();
                System.out.println("path = " + path);
                System.out.println("数据 = " + new String(nodeCache.getCurrentData().getData()));
            }
        });

        //启动监视器
        nodeCache.start();

        Thread.sleep(50000);
        System.out.println("结束");
        //关闭监视器
        nodeCache.close();
    }

    @Test
    public void testWatcher2() throws Exception {
        //监视子节点
        PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/watcher1", true);
        //增加监听器
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                System.out.println("节点的事件类型 = " + event.getType());
                System.out.println("节点的路径 = " + event.getData().getPath());
                System.out.println("数据 = " + new String(event.getData().getData()));
            }
        });

        //启动监视器
        pathChildrenCache.start();

        Thread.sleep(50000);
        System.out.println("结束");
        //关闭监视器
        pathChildrenCache.close();
    }
}

1.11 事务

  • 示例:
package com.sunxiaping.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.Before;
import org.junit.Test;

public class CuratorTx {
    private CuratorFramework client;

    @Before
    public void before() {
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.40.101:2181")
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("hadoop")
                .build();
        client.start();
    }

    @Test
    public void after() {
        if (client != null) {
            client.close();
        }
    }

    @Test
    public void test() throws Exception {
        //开启事务
        client.inTransaction()
                .create()
                .forPath("/node1", "node1".getBytes())
                .and()
                .setData()
                .forPath("/node2", "node2".getBytes())
                .and()
                //事务提交
                .commit();
    }
}

1.12 分布式锁

  • InterProcessMutex:分布式可重入排它锁。

  • InterProcessReadWriteLock:分布式读写锁。

  • 示例:

package com.sunxiaping.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.Before;
import org.junit.Test;

public class CuratorLock {
    private CuratorFramework client;

    @Before
    public void before() {
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.40.101:2181")
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("hadoop")
                .build();
        client.start();
    }

    @Test
    public void after() {
        if (client != null) {
            client.close();
        }
    }

    /**
     * 排它锁
     */
    @Test
    public void test1() throws Exception {
        //arg1:连接对象
        //arg2:节点路径
        InterProcessLock interProcessLock = new InterProcessMutex(client, "/lock1");
        System.out.println("等待获取锁对象");
        //获取锁
        interProcessLock.acquire();
        for (int i = 0; i < 10; i++) {
            Thread.sleep(3000);
            System.out.println("i = " + i);
        }

        //释放锁
        interProcessLock.release();
        System.out.println("等待释放锁");

    }

    /**
     * 读写锁
     */
    @Test
    public void test2() throws Exception {
        //arg1:连接对象
        //arg2:节点路径
        InterProcessReadWriteLock interProcessReadWriteLock = new InterProcessReadWriteLock(client, "/lock1");
        //读锁
        InterProcessLock readLock = interProcessReadWriteLock.readLock();
        System.out.println("等待获取锁对象");
        //获取锁
        readLock.acquire();
        for (int i = 0; i < 10; i++) {
            Thread.sleep(3000);
            System.out.println("i = " + i);
        }

        //释放锁
        readLock.release();
        System.out.println("等待释放锁");
    }


    /**
     * 读写锁
     */
    @Test
    public void test3() throws Exception {
        //arg1:连接对象
        //arg2:节点路径
        InterProcessReadWriteLock interProcessReadWriteLock = new InterProcessReadWriteLock(client, "/lock1");
        //写锁
        InterProcessLock writeLock = interProcessReadWriteLock.writeLock();
        System.out.println("等待获取锁对象");
        //获取锁
        writeLock.acquire();
        for (int i = 0; i < 10; i++) {
            Thread.sleep(3000);
            System.out.println("i = " + i);
        }

        //释放锁
        writeLock.release();
        System.out.println("等待释放锁");
    }
}

2 zookeeper四字监控命令

  • zookeeper支持某些特定的四字命令和其交互,它们大多数查询命令,用来获取zookeeper服务的当前状态及其相关信息。用户在客户端可以通过telnet或nc向zookeeper提交相应的命令。zookeeper常用的四字命令如下表所示:
命令 描述
conf 输出相关服务配置的详细信息。比如端口、zk数据、最大连接数、session超时时间、serverId等。
cons 列出所有连接到这台服务器的客户端连接/会话的详细信息。包括"接受/发送"的包数量、sessionId、操作延迟、最后的操作执行等信息
crst 重置当前这台服务器所有连接/会话统计信息
dump 列出未经处理的会话和临时节点
envi 输出关于服务器的环境详细信息
ruok 测试服务是否处于正确运行状态。如果正常返回"imok",否则返回空。
stat 输出服务器的详细新:接受/发送包数量、连接数、模式(Leader/follower)、节点总数、延迟。所有客户端的列表。
wchs 列出服务器watches的简洁信息:连接总数、watching节点总数和watches总数。
wchc 通过session分组,列出watch的所有节点,它的输出是一个和watch相关的会话的节点列表
mntr 列出集群的健康状态。包括“接受/发送”的包数量、操作延迟、当前服务模式(Leader、follower)、节点总数、watch总数、临时节点总数。
srst 重置server状态
  • telnet命令的安装:
  • 1️⃣查看是否安装telnet和依赖的xinetd:
rpm -qa | grep telnet
  • 2️⃣没有则安装:
yum -y install  xinetd
yum -y install telnet
yum -y install telnet-server
  • 3️⃣telnet默认不开启,修改文件/etc/xinetd.d/telnet来开启服务,修改disable=yes为disable=no。如果telnet文件不存在,则手动新建telnet文件,并添加如下内容:
service telnet         
{  
  flags = REUSE  
  socket_type = stream  
  wait = no  
  user = root  
  server =/usr/sbin/in.telnetd  
  log_on_failure += USERID  
  disable = no   
}
  • 4️⃣启动telnet和xinetd。
systemctl start xinetd
  • 5️⃣加入开机自启动:
systemctl enable xinetd.service
  • 6️⃣telnet的使用:
telnet 192.168.40.101 2181
mntr

  • nc命令的安装:
  • 1️⃣安装命令如下:
yum -y install nmap-ncat.x86_64
  • 2️⃣nc的使用:
echo mntr | nc 192.168.40.101 2181

nc的使用

3 zookeeper图形化的客户端工具(ZooInspector)

  • 下载地址
  • 解压:进入目录的build,使用java -jar zookeeper-dev-ZooInspector.jar运行zookeeper-dev-ZooInspector.jar。

ZooInspector启动界面

原文地址:https://www.cnblogs.com/xuweiweiwoaini/p/13814425.html