新聞中心
第1章 常用命令
zk的應(yīng)用主要是針對(duì)三類:

在紫云等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站制作、做網(wǎng)站 網(wǎng)站設(shè)計(jì)制作定制網(wǎng)站建設(shè),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),成都全網(wǎng)營(yíng)銷,成都外貿(mào)網(wǎng)站建設(shè)公司,紫云網(wǎng)站建設(shè)費(fèi)用合理。
- java原生zk客戶端的API操作(不用去學(xué)這部分內(nèi)容,會(huì)增加太多的學(xué)習(xí)成本,了解一下就好了)。
- zkClient的使用,它是對(duì)Zookeeper原生API的封裝。
- Apache Curator,也是對(duì)Zookeeper API 的封裝(本文講的應(yīng)用針對(duì)這部分內(nèi)容)。
在學(xué)Java API之前,我們先來了解一下zookeeper的常用命令。
連接zookeeper server。
[root@jt2 bin]# sh zkCli.sh -server 127.0.0.1:2181
獲取幫助help。
連接遠(yuǎn)程節(jié)點(diǎn)。
connect 192.168.8.75:2181
關(guān)閉連接。
close
顯示集群。
[zk: localhost:2181(CONNECTED) 0] config
server.0=jt2:2888:3888:participant
server.1=jt3:2888:3888:participant
server.2=jt4:2888:3888:participant
version=0
創(chuàng)建一個(gè)znode。
命令語法:create [-s] [-e] [-c] [-t ttl] path [data] [acl]
-s:創(chuàng)建的是帶序列號(hào)的節(jié)點(diǎn),序列號(hào)用0填充節(jié)點(diǎn)路徑。
-e:創(chuàng)建的是臨時(shí)節(jié)點(diǎn)。
-c:創(chuàng)建的是容器節(jié)點(diǎn)
path:znode的路徑,ZooKeeper中沒有相對(duì)路徑,所有路徑都必須以’/'開頭。
data:znode攜帶的數(shù)據(jù)。
acl:這個(gè)節(jié)點(diǎn)的ACL。
#創(chuàng)建一個(gè)永久節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 2] create /zkBase
Created /zkBase
#創(chuàng)建一個(gè)臨時(shí)節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 3] create -e /ephemeral_node
Created /ephemeral_node
刪除znode節(jié)點(diǎn)。
#刪除節(jié)點(diǎn)前要求節(jié)點(diǎn)目錄為空,不存在子節(jié)點(diǎn)
[zk: localhost:2181(CONNECTED) 34] delete /config
Node not empty: /config
[zk: localhost:2181(CONNECTED) 35] delete /config/topics/test
[zk: localhost:2181(CONNECTED) 27] delete /ephemeral_node
#如果要?jiǎng)h除整個(gè)節(jié)點(diǎn)及子節(jié)點(diǎn)可以使用deleteall
[zk: 192.168.0.143:2181(CONNECTED) 36] deleteall /config
顯示一個(gè)節(jié)點(diǎn)的狀態(tài)。
[zk: localhost:2181(CONNECTED) 11] stat /test
cZxid = 0x180000000e
ctime = Thu Jul 28 03:25:08 CST 2022
mZxid = 0x180000000e
mtime = Thu Jul 28 03:25:08 CST 2022
pZxid = 0x180000000e
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 0
查看路徑子節(jié)點(diǎn)。
命令語法:ls [-s] [-w] [-R] path。
- -s 同時(shí)顯示stat信息。
- -w 只顯示子節(jié)點(diǎn)信息,默認(rèn)選項(xiàng)。
- -R 遞歸顯示。
獲取指定路徑下的數(shù)據(jù)。
[zk: localhost:2181(CONNECTED) 16] get /zookeeper/config
server.0=jt2:2888:3888:participant
server.1=jt3:2888:3888:participant
server.2=jt4:2888:3888:participant
version=0
設(shè)置或者更新路徑數(shù)據(jù)。
[zk: localhost:2181(CONNECTED) 19] set /test/hehe "haha"
[zk: localhost:2181(CONNECTED) 20] get /test/hehe
haha
設(shè)置ACL。
|
ACL權(quán)限 |
ACL 簡(jiǎn)寫 |
允許的操作 |
|
CREATE |
c |
創(chuàng)建子節(jié)點(diǎn) |
|
READ |
r |
獲取節(jié)點(diǎn)的數(shù)據(jù)和它的子節(jié)點(diǎn) |
|
WRITE |
w |
設(shè)置節(jié)點(diǎn)的數(shù)據(jù) |
|
DELETE |
d |
刪除子節(jié)點(diǎn) (僅下一級(jí)節(jié)點(diǎn)) |
|
ADMIN |
a |
設(shè)置 ACL 權(quán)限 |
ZooKeeper內(nèi)置了一些權(quán)限控制方案,可以用以下方案為每個(gè)節(jié)點(diǎn)設(shè)置權(quán)限:
|
方案 |
描述 |
|
world |
只有一個(gè)用戶:anyone,代表所有人(默認(rèn)) |
|
ip |
使用IP地址認(rèn)證 |
|
auth |
使用已添加認(rèn)證的用戶認(rèn)證 |
|
digest |
使用“用戶名:密碼”方式認(rèn)證 |
[zk: localhost:2181(CONNECTED) 21] getAcl /test
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 22] create /mynode1 hello
Created /mynode1
[zk: localhost:2181(CONNECTED) 23] addauth digest admin:admin
[zk: localhost:2181(CONNECTED) 24] setAcl /mynode1 auth:admin:cdrwa
[zk: localhost:2181(CONNECTED) 25] getAcl /mynode1
'digest,'admin:x1nq8J5GOJVPY6zgzhtTtA9izLc=
: cdrwa
同步數(shù)據(jù)集群間數(shù)據(jù)。
[zk: localhost:2181(CONNECTED) 26] sync /
Sync is OK
查看命令執(zhí)行歷史。
[zk: localhost:2181(CONNECTED) 27] history
17 - help
18 - getAllChildrenNumber /zookeeper
19 - set /test/hehe "haha"
20 - get /test/hehe
21 - getAcl /test
22 - create /mynode1 hello
23 - addauth digest admin:admin
24 - setAcl /mynode1 auth:admin:cdrwa
25 - getAcl /mynode1
26 - sync /
27 - history
退出客戶端。
[zk: localhost:2181(CONNECTED) 28] quit
WATCHER::
WatchedEvent state:Closed type:None path:null
2022-07-28 03:33:49,307 [myid:] - INFO [main:ZooKeeper@1422] - Session: 0xcebb0001 closed
2022-07-28 03:33:49,308 [myid:] - INFO [main-EventThread:ClientCnxn$EventThread@524] - EventThread shut down for session: 0xcebb0001
第2章 Java API使用
zookeeper客戶端和服務(wù)器會(huì)話的建立是一個(gè)異步的過程,也就是說在程序中,程序方法在處理完客戶端初始化后立即返回(即程序繼續(xù)往下執(zhí)行代碼,這樣,在大多數(shù)情況下并沒有真正的構(gòu)建好一個(gè)可用會(huì)話,在會(huì)話的生命周期處于“CONNECTED”時(shí)才算真正的建立完畢,所以需要使用到多線程中的一個(gè)工具類CountDownLatch)。
1、創(chuàng)建會(huì)話
(一共有4個(gè)構(gòu)造方法,根據(jù)參數(shù)不同)。
Zookeeper(String connectString,int sessionTimeout,Watcher watcher)
Zookeeper(String connectString,int sessionTimeout,Watcher watcher,boolean canBeReadOnly)
Zookeeper(String connectString,int sessionTimeout,Watcher watcher,long sessionId,byte[] sessionPasswd)
Zookeeper(String connectString,int sessionTimeout,Watcher watcher,long sessionId,byte[] sessionPasswd,boolean canBeReadOnly)
參數(shù)說明:
- connectString :host:port指定的服務(wù)器列表,多個(gè)host:port之間用英文逗號(hào)分隔。還可以可選擇地指定一個(gè)基路徑,如果指定了一個(gè)基路徑,則所有后續(xù)操作基于這個(gè)及路徑進(jìn)行。
- sessionTimeOut:會(huì)話超時(shí)時(shí)間。以毫秒為單位。客戶端和服務(wù)器端之間的連接通過心跳包進(jìn)行維系,如果心跳包超過這個(gè)指定時(shí)間則認(rèn)為會(huì)話超時(shí)失效。
- watcher:指定默認(rèn)觀察者。如果為null表示不需要觀察者。
- canBeReadOnly :是否支持只讀服務(wù)。只當(dāng)一個(gè)服務(wù)器失去過半連接后不能再進(jìn)行寫入操作時(shí),是否繼續(xù)支持讀取操作。
- sessionId、SessionPassword:會(huì)話編號(hào) 會(huì)話密碼(通過兩個(gè)確定唯一一臺(tái)客戶端),用來實(shí)現(xiàn)會(huì)話恢復(fù)(重復(fù)回話)。
注意,整個(gè)創(chuàng)建會(huì)話的過程是異步的,構(gòu)造方法會(huì)在初始化連接后即返回,并不代表真正建立好了一個(gè)會(huì)話,此時(shí)會(huì)話處于"CONNECTING"狀態(tài)。當(dāng)會(huì)話真正創(chuàng)建起來后,服務(wù)器會(huì)發(fā)送事件通知給客戶端,只有客戶端獲取到這個(gè)通知后,會(huì)話才真正建立。
代碼演示:
public class ZkConnect implements Watcher {
private static final Logger log = LoggerFactory.getLogger(ZkConnect.class);
//public static final String zkServerPath = "192.168.8.74:2181,192.168.8.75:2181,192.168.8.76:2181";
public static final String zkServerPath = "127.0.0.1:2181";
public static final Integer timeout = 5000;
public static CountDownLatch countDownLatch = new CountDownLatch(1);
/**
* 客戶端與zkServer連接是一個(gè)異步的過程,當(dāng)連接成功后,客戶端會(huì)收到一個(gè)watch通知
* 參數(shù):
* connectString: 連接服務(wù)器的ip字符串
* sessionTimeout: 超時(shí)時(shí)間,心跳收不到了,就超時(shí)
* watcher: 通知事件,如果有對(duì)應(yīng)的事件觸發(fā),則會(huì)收到一個(gè)通知;如果不需要,就設(shè)置為null
* canBeReadOnly: 可讀,當(dāng)這個(gè)物理機(jī)節(jié)點(diǎn)斷開后,還是可以讀到數(shù)據(jù)的,只是不能寫;此時(shí)數(shù)據(jù)被讀取到的可能
* 是舊數(shù)據(jù),此處建議設(shè)置為false
* sessionId: 會(huì)話id
* sessionPasswd: 會(huì)話密碼,當(dāng)會(huì)話丟失后,可以依據(jù)sessionId和sessionPasswd重新獲取會(huì)話
*/
public static void main(String[] args) throws Exception {
ZooKeeper zk = new ZooKeeper(zkServerPath, timeout, new ZkConnect());
log.warn("客戶端開始連接zookeeper服務(wù)器。連接狀態(tài): {}", zk.getState());
countDownLatch.await(); // 如果不停頓一段時(shí)間, 會(huì)收不到watch通知
log.warn("連接狀態(tài): {}", zk.getState());
}
@Override
public void process(WatchedEvent event) {
log.warn("接收到watch通知: {}", event);
countDownLatch.countDown();
}
}
public class ZkReconnect implements Watcher {
private static final Logger log = LogManager.getLogger(ZkReconnect.class);
public static final String zkServerPath = "127.0.0.1:2181";
public static final Integer timeout = 5000;
public static CountDownLatch countDownLatch1 = new CountDownLatch(1);
public static CountDownLatch countDownLatch2 = new CountDownLatch(2);
public static void main(String[] args) throws Exception {
ZooKeeper zk = new ZooKeeper(zkServerPath, timeout, new ZkReconnect());
long sessionId = zk.getSessionId();
byte[] sessionPasswd = zk.getSessionPasswd();
log.warn("客戶端開始連接zookeeper服務(wù)器。連接狀態(tài): {}", zk.getState());
countDownLatch1.await(); // 如果不停頓一段時(shí)間, 會(huì)收不到watch通知
log.warn("連接狀態(tài): {}", zk.getState());
Thread.sleep(1000);
log.warn("開始會(huì)話重連...");
ZooKeeper zkSession = new ZooKeeper(zkServerPath, timeout, new ZkReconnect(), sessionId, sessionPasswd);
log.warn("重新連接, 狀態(tài): {}", zk.getState());
countDownLatch2.await();
log.warn("重新連接, 狀態(tài): {}", zk.getState());
}
@Override
public void process(WatchedEvent event) {
log.warn("接收到watch通知: {}", event);
countDownLatch1.countDown();
countDownLatch2.countDown();
}
}
2、創(chuàng)建節(jié)點(diǎn)
提供了兩套創(chuàng)建節(jié)點(diǎn)的方法,同步和異步創(chuàng)建節(jié)點(diǎn)方式。
String create(final String path,byte data[],Listacl,CreateMode createMode);//同步方式創(chuàng)建
void create(final String path,byte data[],Listacl,CreateMode createMode,StringCallback cb,Object ctx);//異步方式創(chuàng)建
同步方式:
path:節(jié)點(diǎn)路徑(名稱):/nodeName。不允許遞歸創(chuàng)建節(jié)點(diǎn),在父節(jié)點(diǎn)不存在的情況下,不允許創(chuàng)建子節(jié)點(diǎn)。
data[]:節(jié)點(diǎn)內(nèi)容:要求類型是字節(jié)數(shù)組,也就是說不支持序列話方式,如果需要實(shí)現(xiàn)序列化,可使用java相關(guān)序列化框架,如Hessian,Kryo。
acl:節(jié)點(diǎn)權(quán)限:使用Ids.OPEN_ACL_UNSAFE開放權(quán)限即可。
createMode:節(jié)點(diǎn)類型:創(chuàng)建節(jié)點(diǎn)的類型,CreateMode.*,提供了如下所示的四種節(jié)點(diǎn)類型:
- PERSISTENT(持久節(jié)點(diǎn))。
- PERSISTENT_SEQUENTIAL(持久順序節(jié)點(diǎn))。
- EPHEMERAL(臨時(shí)節(jié)點(diǎn),本次會(huì)話有效)。
- EPHEMERAL_SEQUENTIAL(臨時(shí)順序節(jié)點(diǎn),本次會(huì)話有效)。
異步方式(在同步方法參數(shù)的基礎(chǔ)上增加兩個(gè)參數(shù)):
cb:回調(diào)方法:注冊(cè)一個(gè)異步回調(diào)方法,要實(shí)現(xiàn)。
AsynCallBack.StringCallBack接口,重寫processResult(int rc, String path, Object ctx, String name)方法,當(dāng)節(jié)點(diǎn)創(chuàng)建完成后執(zhí)行此方法。
- rc:服務(wù)端響應(yīng)碼,0表示調(diào)用成功、-4表示端口連接、-110表示指定節(jié)點(diǎn)存在、-112表示會(huì)話已過期。
- path:接口調(diào)用時(shí)傳入的數(shù)據(jù)節(jié)點(diǎn)的路徑參數(shù)。
- ctx:調(diào)用接口傳入的ctx值。
- name:實(shí)際在服務(wù)端創(chuàng)建的節(jié)點(diǎn)的名稱。
ctx:傳遞給回調(diào)方法的參數(shù),一般為上下文(Context)信息。
代碼演示
public class ZkNodeCreate implements Watcher {
private ZooKeeper zooKeeper = null;
private static final Logger log = LoggerFactory.getLogger(ZkNodeCreate.class);
private static final String zkServerPath = "127.0.0.1:2181";
private static final Integer timeout = 5000;
public ZkNodeCreate() {}
public ZkNodeCreate(String connectString) {
try {
zooKeeper = new ZooKeeper(connectString, timeout, new ZkNodeCreate());
} catch (Exception e) {
e.printStackTrace();
if (zooKeeper != null) {
try {
zooKeeper.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
ZkNodeCreate zkNodeOperator = new ZkNodeCreate(zkServerPath);
zkNodeOperator.createZKNode("/testnode", "testnode".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE);
new CountDownLatch(1).await();
}
/**
* 同步或異步創(chuàng)建節(jié)點(diǎn),都不支持子節(jié)點(diǎn)的遞歸創(chuàng)建,異步有一個(gè)callback函數(shù)
* 參數(shù):
* path: 創(chuàng)建的路徑
* data: 存儲(chǔ)的數(shù)據(jù)
* acl: 控制權(quán)限策略. Ids.OPEN_ACL_UNSAFE --> world:anyone:cdrwa
* Ids.CREATOR_ALL_ACL --> auth:user:password:cdrwa
* createMode: 節(jié)點(diǎn)類型,是一個(gè)枚舉
* PERSISTENT 持久節(jié)點(diǎn)
* PERSISTENT_SEQUENTIAL 持久順序節(jié)點(diǎn)
* EPHEMERAL 臨時(shí)節(jié)點(diǎn)
* EPHEMERAL_SEQUENTIAL 臨時(shí)順序節(jié)點(diǎn)
*
* @param path
* @param data
* @param acls
*/
private void createZKNode(String path, byte[] data, ArrayList acls) {
String result = "";
try {
// 同步創(chuàng)建
//result = zooKeeper.create(path, data, acls, CreateMode.EPHEMERAL);
//log.warn("同步創(chuàng)建臨時(shí)節(jié)點(diǎn): {} 成功。", result);
// 異步創(chuàng)建
String ctx = "{'create':'success'}";
zooKeeper.create(path, data, acls, CreateMode.EPHEMERAL, new CreateNodeCallBack(), ctx);
Thread.sleep(5000);
log.warn("異步創(chuàng)建臨時(shí)節(jié)點(diǎn): {} 成功。", result);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void process(WatchedEvent event) {
log.warn("客戶端連接接收到watch通知: {}", event);
}
public ZooKeeper getZooKeeper() {
return zooKeeper;
}
public void setZooKeeper(ZooKeeper zooKeeper) {
this.zooKeeper = zooKeeper;
}
private static class CreateNodeCallBack implements AsyncCallback.StringCallback {
@Override
public void processResult(int rc, String path, Object ctx, String name) {
log.warn("異步創(chuàng)建節(jié)點(diǎn):{}, ctx: {}", path, (String)ctx);
}
}
}
3、節(jié)點(diǎn)操作
修改節(jié)點(diǎn)數(shù)據(jù)。
public class ZkNodeUpdate implements Watcher {
private
分享題目:Zookeeper系列—Zookeeper應(yīng)用及常用命令
轉(zhuǎn)載源于:http://www.5511xx.com/article/ccdosic.html


咨詢
建站咨詢
