本文內容包括:zookeeper 開源客戶端curator介紹、四字監控命令、圖形化的客戶端工具(ZooInspector)
傳送門(已完結):
認認真真學習zookeeper(一)
認認真真學習zookeeper(二)
認認真真學習zookeeper(三)
文章目錄
- 1. zookeeper 開源客戶端curator介紹
- 1.1 curator簡介
- 1.2 連接到ZooKeeper
- 1.3 新增節點
- 1.4 更新節點
- 1.5 刪除節點
- 1.6 查看節點
- 1.7 查看子節點
- 1.8 檢查節點是否存在
- 1.9 watcherAPI
- 1.10 事務
- 1.11 分佈式鎖
- 2. zookeeper四字監控命令
- 2.1 conf命令
- 2.2 cons命令
- 2.3 crst命令
- 2.4 dump命令
- 2.5 envi命令
- 2.6 ruok命令
- 2.7 stat命令
- 2.8 srst命令
- 2.9 wchs命令
- 2.10 wchc命令
- 2.11 wchp命令
- 2.12 mntr命令
- 3. zookeeper圖形化的客戶端工具(ZooInspector)
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