三天学会ZooKeeper第三天(全网最细)

ZooKeeper

  • zookeeper 开源客户端curator介绍
  • zookeeper四字监控命令
  • zookeeper图形化的客户端工具(ZooInspector)
  • taokeeper监控工具的使用

本篇文章来自黑马程序员ZooKeeper教程

三天学会ZooKeeper第一天(全网最细)
三天学会ZooKeeper第二天(全网最细)

zookeeper 开源客户端curator介绍

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. 提供了分布式锁服务、共享计数器、缓存机制等机制

Curator的组件
三天学会ZooKeeper第三天(全网最细)_第1张图片
Maven依赖
三天学会ZooKeeper第三天(全网最细)_第2张图片
我们在实际的应用时,最常用的是curator-recipes。

连接到ZooKeeper

依赖

       <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.2.0</version>
        </dependency>
public class testConnection {
     
    public static void main(String[] args) {
     
        // session重连策略
        /*
        3秒后重连一次,只重连1次
        RetryPolicy retryPolicy = new RetryOneTime(3000);
        */
        /*
        每3秒重连一次,重连3次
        RetryPolicy retryPolicy = new RetryNTimes(3,3000);
        */
        /*
        每3秒重连一次,总等待时间超过10秒后停止重连
        RetryPolicy retryPolicy=new RetryUntilElapsed(10000,3000);
        */
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
       CuratorFramework client = CuratorFrameworkFactory.builder()
               // IP地址端口号
               .connectString("192.168.1.108")
                                // 会话超时时间
                               .sessionTimeoutMs(5000)
                                // 重连机制
                               .retryPolicy(retryPolicy)
                                // 命名空间
                               .namespace("create")
                                // 构建连接对象
                               .build();
       client.start();
        System.out.println(client.isStarted());
        client.close();
    }
}

官网的打开连接方式

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3)
CuratorFramework client = CuratorFrameworkFactory.newClient(zookeeperConnectionString, retryPolicy);
client.start();

新增节点

public class testCreate {
     
    private String ip="192.168.1.108:2181";
    CuratorFramework client;
    RetryPolicy retryPolicy= new RetryUntilElapsed(2000,3);
    @Before
    public void conn(){
     
        client= CuratorFrameworkFactory.builder().connectString(ip).
                sessionTimeoutMs(5000).
                retryPolicy(retryPolicy)
                .namespace("create").build();
        client.start();
    }
    @Test
    public void create()throws Exception{
     
        client.create()
                .withMode(CreateMode.PERSISTENT)
                .withACL(ZooDefs.Ids.READ_ACL_UNSAFE)
                .forPath("/node","node1".getBytes());
        System.out.println("end!!!");
    }
    @Test
    public void create2() throws Exception{
     
        // 自定义权限列表
        // 权限列表
        List<ACL> list = new ArrayList<ACL>();
       // 授权模式和授权对象
        Id id = new Id("ip", "192.168.1.102");
        list.add(new ACL(ZooDefs.Perms.ALL, id));
        client.create().withMode(CreateMode.PERSISTENT).withACL(list).
                forPath("/node2", "node2".getBytes());
                System.out.println("结束");

    }
    @Test
    public void create3()throws Exception{
     
        // 递归创建节点树
        client.create()
                // 递归节点的创建
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT)
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                .forPath("/node3/node31", "node31".getBytes());
        System.out.println("结束");
    }
    @Test
    public void create4() throws Exception {
     
       // 异步方式创建节点
        client.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT)
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                // 异步回调接口
                .inBackground(new BackgroundCallback() {
     
                    public void processResult(CuratorFramework
                                                      curatorFramework, CuratorEvent curatorEvent) throws Exception {
     
                        // 节点的路径
                        System.out.println(curatorEvent.getPath());
                        // 时间类型
                        System.out.println(curatorEvent.getType());
                    }
                })
                .forPath("/node4","node4".getBytes());
        Thread.sleep(5000);
        System.out.println("结束");
    }

    @After
    public void close(){
     
        client.close();
    }
}

更新节点

public class TestSet {
     
    private String ip="192.168.1.102:2181";
    CuratorFramework client;
    RetryPolicy retryPolicy= new RetryUntilElapsed(2000,3);
    @Before
    public void conn(){
     
        client= CuratorFrameworkFactory.builder().connectString(ip).
                sessionTimeoutMs(5000).
                retryPolicy(retryPolicy)
                .namespace("set").build();
        client.start();
    }
    @Test
    public void set1() throws Exception {
     
        // 更新节点
        client.setData()
              // arg1:节点的路径
              // arg2:节点的数据
                .forPath("/node1", "node11".getBytes());
        System.out.println("结束");

    }
    @Test
    public void set2() throws Exception {
     
        client.setData()
               // 指定版本号
                .withVersion(2)
                .forPath("/node1", "node1111".getBytes());
        System.out.println("结束");
    }
    @Test
    public void set3() throws Exception {
     
        // 异步方式修改节点数据
        client.setData()
                .withVersion(-1).inBackground(new BackgroundCallback() {
     
            public void processResult(CuratorFramework curatorFramework,
                                      CuratorEvent curatorEvent) throws Exception {
     
                 // 节点的路径
                System.out.println(curatorEvent.getPath());
               // 事件的类型
                System.out.println(curatorEvent.getType());
            }
        }).forPath("/node1", "node1".getBytes());
        Thread.sleep(5000);
        System.out.println("结束");
    }



    @After
    public void close(){
     
        client.close();
    }
}

删除节点

public class testDelete {
     
    private String ip="192.168.1.102:2181";
    CuratorFramework client;
    RetryPolicy retryPolicy= new RetryUntilElapsed(2000,3);
    @Before
    public void conn(){
     
        client= CuratorFrameworkFactory.builder().connectString(ip).
                sessionTimeoutMs(5000).
                retryPolicy(retryPolicy)
                .namespace("create").build();
        client.start();
    }

    @Test
    public void delete1() throws Exception {
     
      // 删除节点
        client.delete()
     // 节点的路径
                .forPath("/node1");
        System.out.println("结束");
    }
    @Test
    public void delete2() throws Exception {
     
        client.delete()
                // 版本号
                .withVersion(0)
                .forPath("/node1");
        System.out.println("结束");
    }
    @Test
    public void delete3() throws Exception {
     
         //删除包含字节点的节点
        client.delete()
                .deletingChildrenIfNeeded()
                .withVersion(-1)
                .forPath("/node1");
        System.out.println("结束");
    }
    @Test
    public void delete4() throws Exception {
     
        // 异步方式删除节点
        client.delete()
                .deletingChildrenIfNeeded()
                .withVersion(-1)
                .inBackground(new BackgroundCallback() {
     
                    public void processResult(CuratorFramework
                                                      curatorFramework, CuratorEvent curatorEvent) throws Exception {
     
                       // 节点路径
                        System.out.println(curatorEvent.getPath());
                       // 事件类型
                        System.out.println(curatorEvent.getType());
                    }
                })
                .forPath("/node1");
        Thread.sleep(5000);
        System.out.println("结束");
    }
    @After
    public void close(){
     
        client.close();
    }
}

查看节点

public class TestGet {
     
    private String ip="192.168.1.102:2181";
    CuratorFramework client;
    RetryPolicy retryPolicy= new RetryUntilElapsed(2000,3);
    @Before
    public void conn(){
     
        client= CuratorFrameworkFactory.builder().connectString(ip).
                sessionTimeoutMs(5000).
                retryPolicy(retryPolicy)
                .namespace("create").build();
        client.start();
    }
    @Test
    public void get1() throws Exception {
     
          // 读取节点数据
        byte [] bys=client.getData()
           // 节点的路径
                .forPath("/node1");
        System.out.println(new String(bys));
    }
    @Test
    public void get2() throws Exception {
     
     // 读取数据时读取节点的属性
        Stat stat=new Stat();
        byte [] bys=client.getData()
            // 读取属性
                .storingStatIn(stat)
                .forPath("/node1");
        System.out.println(new String(bys));
        System.out.println(stat.getVersion());
    }
    @Test
    public void get3() throws Exception {
     
           // 异步方式读取节点的数据
        client.getData()
                .inBackground(new BackgroundCallback() {
     
                    public void processResult(CuratorFramework
                                                      curatorFramework, CuratorEvent curatorEvent) throws Exception {
     
                       // 节点的路径
                        System.out.println(curatorEvent.getPath());
                        // 事件类型
                        System.out.println(curatorEvent.getType());
                        // 数据
                        System.out.println(new
                                String(curatorEvent.getData()));
                    }
                })
                .forPath("/node1");
        Thread.sleep(5000);
        System.out.println("结束");
    }
    @After
    public void close(){
     
        client.close();
    }
}

查看子节点

public class TestGetchlden {
     

    private String ip="192.168.1.102:2181";
    CuratorFramework client;
    RetryPolicy retryPolicy= new RetryUntilElapsed(2000,3);
    @Before
    public void conn(){
     
        client= CuratorFrameworkFactory.builder().connectString(ip).
                sessionTimeoutMs(5000).
                retryPolicy(retryPolicy)
                .namespace("get").build();
        client.start();
    }
    @After
    public void close(){
     
        client.close();
    }
    @Test
    public void getChild1() throws Exception {
     
     // 读取子节点数据
        List<String> list = client.getChildren()
        // 节点路径
        .forPath("/get");
        for (String str : list) {
     
            System.out.println(str);
        }
    }
    @Test
    public void getChild2() throws Exception {
     
          // 异步方式读取子节点数据
        client.getChildren()
                .inBackground(new BackgroundCallback() {
     
                    public void processResult(CuratorFramework
                                                      curatorFramework, CuratorEvent curatorEvent) throws Exception {
     
                       // 节点路径
                        System.out.println(curatorEvent.getPath());
                      // 事件类型
                        System.out.println(curatorEvent.getType());
                        // 读取子节点数据
                        List<String> list=curatorEvent.getChildren();
                        for (String str : list) {
     
                            System.out.println(str);
                        }
                    }
                })
                .forPath("/get");
        Thread.sleep(5000);
        System.out.println("结束");
    }
}

检查子节点是否存在

public class TestExist {
     

    private String ip="192.168.1.102:2181";
    CuratorFramework client;
    RetryPolicy retryPolicy= new RetryUntilElapsed(2000,3);
    @Before
    public void conn(){
     
        client= CuratorFrameworkFactory.builder().connectString(ip).
                sessionTimeoutMs(5000).
                retryPolicy(retryPolicy)
                .namespace("get").build();
        client.start();
    }
    @After
    public void close(){
     
        client.close();
    }
    @Test
    public void exists1() throws Exception {
     
         // 判断节点是否存在
        Stat stat= client.checkExists()
                // 节点路径
                .forPath("/node2");
        System.out.println(stat.getVersion());
    }
    @Test
    public void exists2() throws Exception {
     
         // 异步方式判断节点是否存在
        client.checkExists()
                .inBackground(new BackgroundCallback() {
     
                    public void processResult(CuratorFramework
                                                      curatorFramework, CuratorEvent curatorEvent) throws Exception {
     
                         // 节点路径
                        System.out.println(curatorEvent.getPath());
                        // 事件类型
                        System.out.println(curatorEvent.getType());
                        System.out.println(curatorEvent.getStat().getVersion());
                    }
                })
                .forPath("/node2");
        Thread.sleep(5000);
        System.out.println("结束");
    }
}

watcherAPI

Node Cache : 只是监听某一个特定的节点,监听节点的新增和修改
PathChildren Cache : 监控一个ZNode的子节点. 当一个子节点增加, 更新,删除
时, Path Cache会改变它的状态, 会包含最新的子节点, 子节点的数据和状态

public class CuratorWatcher {
     
    private String ip="192.168.1.108:2181";
    CuratorFramework client;
    RetryPolicy retryPolicy= new RetryUntilElapsed(2000,3);
    @Before
    public void conn(){
     
        client= CuratorFrameworkFactory.builder().connectString(ip).
                sessionTimeoutMs(5000).
                retryPolicy(retryPolicy)
                .namespace("create").build();
        client.start();
    }
    @After
    public void close(){
     
        client.close();
    }
    @Test
    public void watcher1() throws Exception {
     
        // 监视某个节点的数据变化
        // arg1:连接对象
        // arg2:监视的节点路径
        final NodeCache nodeCache=new NodeCache(client,"/watcher1");
        // 启动监视器对象
        nodeCache.start();
        nodeCache.getListenable().addListener(new NodeCacheListener() {
     
            // 节点变化时回调的方法
            public void nodeChanged() throws Exception {
     
                System.out.println(nodeCache.getCurrentData().getPath());
                System.out.println(new
                        String(nodeCache.getCurrentData().getData()));
            }
        });
        Thread.sleep(100000);
        System.out.println("结束");
		//关闭监视器对象
        nodeCache.close();
    }
    @Test
    public void watcher2() throws Exception {
     
        // 监视子节点的变化
        // arg1:连接对象
        // arg2:监视的节点路径
        // arg3:事件中是否可以获取节点的数据
        PathChildrenCache pathChildrenCache=new PathChildrenCache(client,"/watcher1",true);
        // 启动监听
        pathChildrenCache.start();
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
     
                                                                  // 当子节点方法变化时回调的方法
                                                                  public void childEvent(CuratorFramework curatorFramework,
                                                                                         PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
     
                                                                     // 节点的事件类型
                                                                      System.out.println(pathChildrenCacheEvent.getType());
                                                                        // 节点的路径
                                                                      System.out.println(pathChildrenCacheEvent.getData().getPath());
                                                                        // 节点数据
                                                                      System.out.println(new
                                                                              String(pathChildrenCacheEvent.getData().getData()));
                                                                  }
                                                              });
        Thread.sleep(100000);
        System.out.println("结束");
        // 关闭监听
        pathChildrenCache.close();
    }
}

事务

public class TestTranction {
     
    private String ip="192.168.1.102:2181";
    CuratorFramework client;
    RetryPolicy retryPolicy= new RetryUntilElapsed(2000,3);
    @Before
    public void conn(){
     
        client= CuratorFrameworkFactory.builder().connectString(ip).
                sessionTimeoutMs(5000).
                retryPolicy(retryPolicy)
                .namespace("get").build();
        client.start();
    }
    @After
    public void close(){
     
        client.close();
    }
    @Test
    public void Watch()throws Exception{
     
        client.inTransaction().
                create().forPath("node1", "node1".getBytes()).
                and().
                create().forPath("node2", "node2".getBytes()).
                and().
                commit();

    }
}

分布式锁

InterProcessMutex:分布式可重入排它锁
InterProcessReadWriteLock:分布式读写锁

public class CuratorLock {
     
    private String ip="192.168.1.102:2181";
    CuratorFramework client;
    RetryPolicy retryPolicy= new RetryUntilElapsed(2000,3);
    @Before
    public void conn(){
     
        client= CuratorFrameworkFactory.builder().connectString(ip).
                sessionTimeoutMs(5000).
                retryPolicy(retryPolicy)
                .namespace("get").build();
        client.start();
    }
    @After
    public void close(){
     
        client.close();
    }
    @Test
    public void lock1() throws Exception {
     
        // 排他锁
        // arg1:连接对象
        // arg2:节点路径
        InterProcessLock interProcessLock = new InterProcessMutex(client,
                "/lock1");
        System.out.println("等待获取锁对象!");
        // 获取锁
        interProcessLock.acquire();
        for (int i = 1; i <= 10; i++) {
     
            Thread.sleep(3000);
            System.out.println(i);
        }
        // 释放锁
        interProcessLock.release();
        System.out.println("等待释放锁!");
    }
    @Test
    public void lock2() throws Exception {
     
        // 读写锁
        InterProcessReadWriteLock interProcessReadWriteLock=new
                InterProcessReadWriteLock(client, "/lock1");
        // 获取读锁对象
        InterProcessLock
                interProcessLock=interProcessReadWriteLock.readLock();
        System.out.println("等待获取锁对象!");
        // 获取锁
        interProcessLock.acquire();
        for (int i = 1; i <= 10; i++) {
     
            Thread.sleep(3000);
            System.out.println(i);
        }
        // 释放锁
        interProcessLock.release();
        System.out.println("等待释放锁!");
    }
    @Test
    public void lock3() throws Exception {
     
        // 读写锁2.zookeeper
        InterProcessReadWriteLock interProcessReadWriteLock=new
                InterProcessReadWriteLock(client, "/lock1");
        // 获取写锁对象
        InterProcessLock
                interProcessLock=interProcessReadWriteLock.writeLock();
        System.out.println("等待获取锁对象!");
        // 获取锁
        interProcessLock.acquire();
        for (int i = 1; i <= 10; i++) {
     
            Thread.sleep(3000);
            System.out.println(i);
        }
        // 释放锁
        interProcessLock.release();
        System.out.println("等待释放锁!");
    }
}

zookeeper四字监控命令

zooKeeper支持某些特定的四字命令与其的交互。它们大多是查询命令,用来
获取 zooKeeper服务的当前状态及相关信息。用户在客户端可以通过 telnet 或 nc 向zooKeeper提交相应的命令。

四字命令格式:

echo [command] | nc [ip] [port]

zooKeeper常用四字命令见下表 所示:
三天学会ZooKeeper第三天(全网最细)_第3张图片

nc命令工具安装:

#root用户安装
#下载安装包
wget http://vault.centos.org/6.6/os/x86_64/Packages/nc-1.84-
22.el6.x86_64.rpm
#rpm安装
rpm -iUv nc-1.84-22.el6.x86_64.rpm

三天学会ZooKeeper第三天(全网最细)_第4张图片

echo mntr | nc localhost 2181

三天学会ZooKeeper第三天(全网最细)_第5张图片
conf命令

conf:输出相关服务配置的详细信息
shell终端输入:echo conf| nc localhost 2181
三天学会ZooKeeper第三天(全网最细)_第6张图片
三天学会ZooKeeper第三天(全网最细)_第7张图片

cons命令

cons:列出所有连接到这台服务器的客户端连接/会话的详细信息
shell终端输入:echo cons| nc localhost 2181

[root@localhost bin]# echo cons |nc localhost 2181
 /0:0:0:0:0:0:0:1:35706[0](queued=0,recved=1,sent=0)
 /127.0.0.1:48042[1](queued=0,recved=2,sent=2,sid=0x179cb9a49b80000,lop=PING,est=1622619217920,
 to=30000,lcxid=0x0,lzxid=0xd,lresp=1622619227956,llat=0,minlat=0,avglat=1,maxlat=3)

三天学会ZooKeeper第三天(全网最细)_第8张图片
crst命令

crst:重置当前这台服务器所有连接/会话的统计信息
shell终端输入:echo crst| nc localhost 2181

dump命令

dump:列出未经处理的会话和临时节点
shell终端输入:echo dump| nc localhost 2181
三天学会ZooKeeper第三天(全网最细)_第9张图片
三天学会ZooKeeper第三天(全网最细)_第10张图片
envi命令

envi:输出关于服务器的环境配置信息
shell终端输入:echo envi| nc localhost 2181
三天学会ZooKeeper第三天(全网最细)_第11张图片
三天学会ZooKeeper第三天(全网最细)_第12张图片
ruok命令

ruok:测试服务是否处于正确运行状态
shell终端输入:echo ruok| nc localhost 2181

stat命令

stat:输出服务器的详细信息与srvr相似,但是多了每个连接的会话信息

shell终端输入:

echo stat| nc localhost 2181

三天学会ZooKeeper第三天(全网最细)_第13张图片
三天学会ZooKeeper第三天(全网最细)_第14张图片
srst命令

srst:重置server状态
shell终端输入:echo srst| nc localhost 2181

wchs命令

wchs:列出服务器watches的简洁信息
shell终端输入:echo wchs| nc localhost 2181
在这里插入图片描述
三天学会ZooKeeper第三天(全网最细)_第15张图片
wchc命令

wchc:通过session分组,列出watch的所有节点,它的输出的是一个与 watch 相关的会话的节点列表
shell终端输入:echo wchc| nc localhost 2181
问题
在这里插入图片描述
解决方法:

# 修改启动指令 zkServer.sh
# 注意找到这个信息
else
echo "JMX disabled by user request" >&2
ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain"
fi
# 下面添加如下信息
ZOOMAIN="-Dzookeeper.4lw.commands.whitelist=* ${ZOOMAIN}"

wchp命令

wchp:通过路径分组,列出所有的 watch 的session id信息
shell终端输入:echo wchc| nc localhost 2181
问题

wchp is not executed because it is not in the whitelist.

解决方法:

# 修改启动指令 zkServer.sh
# 注意找到这个信息
else
echo "JMX disabled by user request" >&2
ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain"
fi
# 下面添加如下信息
ZOOMAIN="-Dzookeeper.4lw.commands.whitelist=* ${ZOOMAIN}"

mntr命令

mntr:列出服务器的健康状态
shell终端输入:echo mntr| nc localhost 2181
三天学会ZooKeeper第三天(全网最细)_第16张图片
三天学会ZooKeeper第三天(全网最细)_第17张图片

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

ZooInspector下载地址:

https://issues.apache.org/jira/secure/attachment/12436620/ZooInspector.zip

解压后进入目录ZooInspector\build,运行zookeeper-dev-ZooInspector.jar

#执行命令如下
java -jar zookeeper-dev-ZooInspector.jar

三天学会ZooKeeper第三天(全网最细)_第18张图片
三天学会ZooKeeper第三天(全网最细)_第19张图片

taokeeper监控工具的使用

基于zookeeper的监控管理工具taokeeper,由淘宝团队开源的zk管理中间件,安装前要求服务前先配置nc 和 sshd

1.下载数据库脚本

wget https://github.com/downloads/alibaba/taokeeper/taokeeper.sql

2.下载主程序

wget wget https://github.com/downloads/alibaba/taokeeper/taokeeper-monitor.tar.gz

3.下载配置文件

wget https://github.com/downloads/alibaba/taokeeper/taokeeper-monitor-config.properties

4.配置 taokeeper-monitor-config.properties

wget https://github.com/downloads/alibaba/taokeeper/taokeeper-monitorconfig.properties5.安装配置 tomcat,修改catalina.sh
6.部署工程启动
#Daily
systemInfo.envName=DAILY
#DBCP
dbcp.driverClassName=com.mysql.jdbc.Driver
#mysql连接的ip地址端口号
dbcp.dbJDBCUrl=jdbc:mysql://192.168.60.130:3306/taokeeper
dbcp.characterEncoding=GBK
#用户名
dbcp.username=root
#密码
dbcp.password=root
dbcp.maxActive=30
dbcp.maxIdle=10
dbcp.maxWait=10000
#SystemConstant
#用户存储内部数据的文件夹
#创建/home/zookeeper/taokeeperdata/ZooKeeperClientThroughputStat
SystemConstent.dataStoreBasePath=/home/zookeeper/taokeeperdata
#ssh用户
SystemConstant.userNameOfSSH=zookeeper
#ssh密码
SystemConstant.passwordOfSSH=zookeeper
#Optional
SystemConstant.portOfSSH=22
#指向配置文件所在的位置
JAVA_OPTS=-DconfigFilePath="/home/zookeeper/taokeeper-monitortomcat/webapps/ROOT/conf/taokeeper-monitor-config.properties

5.安装配置 tomcat,修改catalina.sh

#指向配置文件所在的位置
JAVA_OPTS=-DconfigFilePath="/home/zookeeper/taokeeper-monitortomcat/webapps/ROOT/conf/taokeeper-monitor-config.propert

6.部署工程启动

你可能感兴趣的:(ZooKeeper,zookeeper,分布式,java)