認認真真學習zookeeper(三)

本文內容包括:zookeeper 開源客戶端curator介紹、四字監控命令、圖形化的客戶端工具(ZooInspector)

傳送門(已完結):
認認真真學習zookeeper(一)
認認真真學習zookeeper(二)
認認真真學習zookeeper(三)

1. zookeeper 開源客戶端curator介紹

1.1 curator簡介

  curator是Netflix公司開源的一個zookeeper客戶端,後捐獻給apache,curator框架在zookeeper原生API接口上進行了包裝,解決了很多zooKeeper客戶端非常底層的細節開發。提供zooKeeper各種應用場景(比如:分佈式鎖服務、集羣領導選舉、共享計數器、緩存機制、分佈式隊列等)的抽象封裝,實現了Fluent風格的API接口,是最好用,最流行的zookeeper的客戶端。

  原生zookeeperAPI的不足:

  • 連接對象異步創建,需要開發人員自行編碼等待
  • 連接沒有自動重連超時機制
  • watcher一次註冊生效一次
  • 不支持遞歸創建樹形節點

  curator特點:

  • 解決session會話超時重連
  • watcher反覆註冊
  • 簡化開發api
  • 遵循Fluent風格的API
  • 提供了分佈式鎖服務、共享計數器、緩存機制等機制

  maven依賴:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.7</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
        <version>2.6.0</version>
        <type>jar</type>
        <exclusions>
            <exclusion>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.10</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
        <version>2.6.0</version>
        <type>jar</type>
    </dependency>
</dependencies>

1.2 連接到ZooKeeper

  案例:

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.RetryOneTime;

public class CuratorConnection {
    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);
       */
        // baseSleepTimeMs * Math.max(1, random.nextInt(1 << (retryCount + 1)))
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);

        // 創建連接對象
        CuratorFramework client= CuratorFrameworkFactory.builder()
                // IP地址端口號
                .connectString("192.168.188.134:2181,192.168.188.134:2182,192.168.188.134:2183")
                // 會話超時時間
                .sessionTimeoutMs(5000)
                // 重連機制
                //.retryPolicy(retryPolicy)
                .retryPolicy(retryPolicy)
                // 命名空間
                .namespace("create")
                // 構建連接對象
                .build();
        // 打開連接
        client.start();
        System.out.println(client.isStarted());
        // 關閉連接
        client.close();
    }
}

1.3 新增節點

  案例:

import org.apache.curator.RetryPolicy;
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.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;


public class CuratorCreate {

    private String IP = "192.168.188.134:2181,192.168.188.134:2182,192.168.188.134:2183";
    private CuratorFramework client;

    @Before
    public void before() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory.builder()
                .connectString(IP)
                .sessionTimeoutMs(5000)
                .retryPolicy(retryPolicy)
                .namespace("create")
                .build();
        client.start();
    }

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

    @Test
    public void create1() throws Exception {
        // 新增節點
        client.create()
                // 節點的類型
                .withMode(CreateMode.PERSISTENT)
                // 節點的權限列表 world:anyone:cdrwa
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                // arg1:節點的路徑
                // arg2:節點的數據
                .forPath("/node1", "hello".getBytes());
        System.out.println("結束");
    }


    @Test
    public void create2() throws Exception {
        // 自定義權限列表
        // 權限列表
        List<ACL> list = new ArrayList<ACL>();
        // 授權模式和授權對象
        Id id = new Id("ip", "192.168.188.134");
        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("結束");
    }
}

1.4 更新節點

​   案例:

import org.apache.curator.RetryPolicy;
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.After;
import org.junit.Before;
import org.junit.Test;

public class CuratorSet {

    String IP = "192.168.188.134:2181,192.168.188.134:2182,192.168.188.134:2183";
    CuratorFramework client;

    @Before
    public void before() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory.builder()
                .connectString(IP)
                .sessionTimeoutMs(5000)
                .retryPolicy(retryPolicy)
                .namespace("set").build();
        client.start();
    }

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

    @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(1)
                .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("結束");
    }
}

1.5 刪除節點

  案例:

import org.apache.curator.RetryPolicy;
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.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;

public class CuratorDelete {

    String IP = "192.168.188.134:2181,192.168.188.134:2182,192.168.188.134:2183";
    CuratorFramework client;

    @Before
    public void before() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory.builder()
            .connectString(IP)
                .sessionTimeoutMs(10000)
                .retryPolicy(retryPolicy)
                .namespace("delete").build();
        client.start();
}

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

    @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("結束");
    }
}

1.6 查看節點

  案例:

import org.apache.curator.RetryPolicy;
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.After;
import org.junit.Before;
import org.junit.Test;

public class CuratorGet {

    String IP = "192.168.188.134:2181,192.168.188.134:2182,192.168.188.134:2183";
    CuratorFramework client;

    @Before
    public void before() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory.builder()
                .connectString(IP)
                .sessionTimeoutMs(10000).retryPolicy(retryPolicy)
                .namespace("get").build();
        client.start();
    }

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

    @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("結束");
    }
}

1.7 查看子節點

  案例:

import org.apache.curator.RetryPolicy;
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.After;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class CuratorGetChild {


    String IP = "192.168.188.134:2181,192.168.188.134:2182,192.168.188.134:2183";
    CuratorFramework client;

    @Before
    public void before() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory.builder()
                .connectString(IP)
                .sessionTimeoutMs(10000)
                .retryPolicy(retryPolicy)
                .build();
        client.start();
    }

    @After
    public void after() {
        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("結束");
    }
}

1.8 檢查節點是否存在

  案例:

import org.apache.curator.RetryPolicy;
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.After;
import org.junit.Before;
import org.junit.Test;

public class CuratorExists {

    String IP = "192.168.188.134:2181,192.168.188.134:2182,192.168.188.134:2183";
    CuratorFramework client;

    @Before
    public void before() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory.builder()
                .connectString(IP)
                .sessionTimeoutMs(10000).retryPolicy(retryPolicy)
                .namespace("get").build();
        client.start();
    }

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

    @Test
    public void exists1() throws Exception {
        // 判斷節點是否存在
       Stat stat= client.checkExists()
                 // 節點路徑
                .forPath("/node1");
        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("/node1");
        Thread.sleep(5000);
        System.out.println("結束");
    }
}

1.9 watcherAPI

  curator提供了兩種Watcher(Cache)來監聽結點的變化

  • Node Cache : 只是監聽某一個特定的節點,監聽節點的新增和修改
  • PathChildren Cache : 監控一個ZNode的子節點. 當一個子節點增加, 更新,刪除時, Path Cache會改變它的狀態, 會包含最新的子節點, 子節點的數據和狀態

​案例:

import org.apache.curator.RetryPolicy;
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.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class CuratorWatcher {

    String IP = "192.168.188.134:2181,192.168.188.134:2182,192.168.188.134:2183";
    CuratorFramework client;

    @Before
    public void before() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory
                .builder()
                .connectString(IP)
                .sessionTimeoutMs(10000)
                .retryPolicy(retryPolicy)
                .build();
        client.start();
    }

    @After
    public void after() {
        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();

    }
}

1.10 事務

  案例:

import org.apache.curator.RetryPolicy;
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.After;
import org.junit.Before;
import org.junit.Test;

public class CuratorTransaction {

    String IP = "192.168.188.134:2181,192.168.188.134:2182,192.168.188.134:2183";
    CuratorFramework client;

    @Before
    public void before() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory.builder()
                .connectString(IP)
                .sessionTimeoutMs(10000).retryPolicy(retryPolicy)
                .namespace("create").build();
        client.start();
    }

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

    @Test
    public void tra1() throws Exception {
        // 開啓事務
        client.inTransaction()
                .create().forPath("/node1","node1".getBytes())
                .and()
                .setData().forPath("/node2","node2".getBytes())
                .and()
                //事務提交
                .commit();
    }
}

1.11 分佈式鎖

  InterProcessMutex:分佈式可重入排它鎖
​  InterProcessReadWriteLock:分佈式讀寫鎖
​  案例:

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
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.framework.recipes.locks.InterProcessSemaphoreMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class CuratorLock {

    String IP = "192.168.188.134:2181,192.168.188.134:2182,192.168.188.134:2183";
    CuratorFramework client;

    @Before
    public void before() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        client = CuratorFrameworkFactory
                .builder()
                .connectString(IP)
                .sessionTimeoutMs(10000)
                .retryPolicy(retryPolicy)
                .build();
        client.start();
    }

    @After
    public void after() {
        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 {
        // 讀寫鎖
        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("等待釋放鎖!");
    }
}

2. zookeeper四字監控命令

  zooKeeper支持某些特定的四字命令與其的交互。它們大多是查詢命令,用來獲取 zooKeeper服務的當前狀態及相關信息。用戶在客戶端可以通過 telnet 或 nc 向zooKeeper提交相應的命令。 zooKeeper常用四字命令見下表 所示:

命令 描述
conf 輸出相關服務配置的詳細信息。比如端口、zk數據及日誌配置路徑、最大連接數,session超時時間、serverId等
cons 列出所有連接到這臺服務器的客戶端連接/會話的詳細信息。包括“接受/發送”的包數量、session id 、操作延遲、最後的操作執行等信息
crst 重置當前這臺服務器所有連接/會話的統計信息
dump 列出未經處理的會話和臨時節點
envi 輸出關於服務器的環境詳細信息
ruok 測試服務是否處於正確運行狀態。如果正常返回"imok",否則返回空
stat 輸出服務器的詳細信息:接收/發送包數量、連接數、模式(leader/follower)、節點總數、延遲。 所有客戶端的列表
srst 重置server狀態
wchs 列出服務器watches的簡潔信息:連接總數、watching節點總數和watches總數
wchc 通過session分組,列出watch的所有節點,它的輸出是一個與 watch 相關的會話的節點列表
mntr 列出集羣的健康狀態。包括“接受/發送”的包數量、操作延遲、當前服務模式(leader/follower)、節點總數、watch總數、臨時節點總數

nc命令查看:

echo mntr | nc 192.168.188.134 2181

telnet命令查看:

telnet 192.168.188.134 2181
mntr

2.1 conf命令

  conf:輸出相關服務配置的詳細信息
  shell終端輸入:echo conf| nc localhost 2181

屬性 含義
clientPort 客戶端端口號
dataDir 數據快照文件目錄 默認情況下100000次事務操作生成一次快照
dataLogDir 事物日誌文件目錄,生產環境中放在獨立的磁盤上
tickTime 服務器之間或客戶端與服務器之間維持心跳的時間間隔(以毫秒爲單位)
maxClientCnxns 最大連接數
minSessionTimeout 最小session超時 minSessionTimeout=tickTime*2
maxSessionTimeout 最大session超時 maxSessionTimeout=tickTime*20
serverId 服務器編號
initLimit 集羣中的follower服務器(F)與leader服務器(L)之間初始連接時能容忍的最多心跳數
syncLimit 集羣中的follower服務器(F)與leader服務器(L)之間 請求和應答之間能容忍的最多心跳數
electionAlg 0:基於UDP的LeaderElection 1:基於UDP的FastLeaderElection 2:基於UDP和認證的FastLeaderElection 3:基於TCP的FastLeaderElection 在3.4.10版本中,默認值爲3另外三種算法已經被棄用,並且有計劃在之後的版本中將它們徹底刪除而不再支持
electionPort 選舉端口
quorumPort 數據通信端口
peerType 是否爲觀察者 1爲觀察者

2.2 cons命令

  cons:列出所有連接到這臺服務器的客戶端連接/會話的詳細信息
​  shell終端輸入:echo cons| nc localhost 2181

屬性 含義
ip ip地址
port 端口號
queued 等待被處理的請求數,請求緩存在隊列中
received 收到的包數
sent 發送的包數
sid 會話id
lop 最後的操作 GETD-讀取數據 DELE-刪除數據 CREA-創建數據
est 連接時間戳
to 超時時間
lcxid 當前會話的操作id
lzxid 最大事務id
lresp 最後響應時間戳
llat 最後/最新 延時
minlat 最小延時
maxlat 最大延時
avglat 平均延時

2.3 crst命令

  crst:重置當前這臺服務器所有連接/會話的統計信息
  shell終端輸入:echo crst| nc localhost 2181

2.4 dump命令

  dump:列出未經處理的會話和臨時節點
  shell終端輸入:echo dump| nc localhost 2181

屬性 含義
session id znode path(1對多 , 處於隊列中排隊的session和臨時節點)

2.5 envi命令

  envi:輸出關於服務器的環境配置信息
  ​shell終端輸入:echo envi| nc localhost 2181

屬性 含義
zookeeper.version 版本
host.name host信息
java.version java版本
java.vendor 供應商
java.home 運行環境所在目錄
java.class.path classpath
java.library.path 第三方庫指定非java類包的位置(如:dll,so)
java.io.tmpdir 默認的臨時文件路徑
java.compiler JIT 編譯器的名稱
os.name Linux
os.arch amd64
os.version 3.10.0-1127.el7.x86_64
user.name root
user.home /root
user.dir /opt/zookeeper2181/bin

2.6 ruok命令

  ruok:測試服務是否處於正確運行狀態
  ​shell終端輸入:echo ruok| nc localhost 2181

2.7 stat命令

  ​stat:輸出服務器的詳細信息與srvr相似,但是多了每個連接的會話信息
  ​​shell終端輸入:echo stat| nc localhost 2181

屬性 含義
Zookeeper version 版本
Latency min/avg/max 延時
Received 收包
Sent 發包
Connections 連接數
Outstanding 堆積數
Zxid 最大事物id
Mode 服務器角色
Node count 節點數

2.8 srst命令

  ​​srst:重置server狀態
  ​​​shell終端輸入:echo srst| nc localhost 2181

2.9 wchs命令

  wchs:列出服務器watches的簡潔信息
  ​shell終端輸入:echo wchs| nc localhost 2181

屬性 含義
connectsions 連接數
watch-paths watch節點數
watchers watcher數量

2.10 wchc命令

  wchc:通過session分組,列出watch的所有節點,它的輸出的是一個與 watch 相關的會話的節點列表
  問題:

wchc 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}"

shell終端輸入:echo wchc| nc localhost 2181

2.11 wchp命令

  wchp:通過路徑分組,列出所有的 watch 的session id信息
  問題:

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}"

shell終端輸入:echo wchp| nc localhost 2181

2.12 mntr命令

  mntr:列出服務器的健康狀態

屬性 含義
zk_version 版本
zk_avg_latency 平均延時
zk_max_latency 最大延時
zk_min_latency 最小延時
zk_packets_received 收包數
zk_packets_sent 發包數
zk_num_alive_connections 連接數
zk_outstanding_requests 堆積請求數
zk_server_state leader/follower 狀態
zk_znode_count znode數量
zk_watch_count watch數量
zk_ephemerals_count 臨時節點(znode)
zk_approximate_data_size 數據大小
zk_open_file_descriptor_count 打開的文件描述符數量
zk_max_file_descriptor_count 最大文件描述符數量

shell終端輸入:echo mntr| nc localhost 2181

3. 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

在這裏插入圖片描述
點擊左上角連接按鈕,輸入zk服務地址:ip或者主機名:2181

在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章