日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Zookeeper C API 指南

發(fā)布時(shí)間:2025/3/21 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Zookeeper C API 指南 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

以前自己的博客中轉(zhuǎn)載、翻譯或?qū)戇^(guò)(不過(guò)自己才疏學(xué)淺,寫(xiě)的不好)一些 Zookeeper 方面的文章,但是都沒(méi)有涉及到 Zookeeper C API 的內(nèi)容,今天的這篇博客是我農(nóng)歷新年的第一篇技術(shù)博客,我想詳細(xì)講講 Zookeeper C API 的使用規(guī)則和示例,算是把以前的舊帳還上吧 :-)

Zookeeper 官方頁(yè)面上提供了一些編程指南和 API 文檔,不過(guò)大部分都是 Java 示例,涉及 C API 的部分很少,只有在 ZooKeeper Programmer's Guide 中 ACL Permissions 一節(jié)講了 Zookeeper C API 中設(shè)置 ACL 應(yīng)該注意的事項(xiàng),正是由于缺少Zookeeper C API 相關(guān)的資料,大部分 Zookeeper C/C++ 開(kāi)發(fā)者只能通過(guò)閱讀 Zookeeper C API 的源碼來(lái)了解 C API 的使用方法,本文希望在此方面給大家提供一些便利,減少 Zookeeper 新手使用 C API 的困難和恐懼,當(dāng)然我自己也是一枚新手啦 :-)。

廢話不多說(shuō)了,先從最基本的開(kāi)始吧!

Zookeeper 偽分布式安裝

首先是 Zookeeper 的安裝,如果你沒(méi)有足夠的機(jī)器,建議在單機(jī)上通過(guò)偽分布式安裝方法來(lái)模擬 Zookeeper 集群,我在這里提供給大家一個(gè)簡(jiǎn)單的安裝包來(lái)降低偽分布式 Zookeeper 的安裝難度,該安裝包可以模擬一個(gè) 5 Zookeeper 實(shí)例的集群。下載zookeeper-3.4.0-pseudoclusters.tar.bz2,解壓至 /tmp/ 目錄(注意,安裝包里面 dataDir 和 dataLogDir 配置已經(jīng)預(yù)設(shè)為 /tmp/ 目錄,如果你只是自己在 Zookeeper 上做一些小實(shí)驗(yàn),建議不要更改該配置,這樣在你做完了實(shí)驗(yàn)以后刪除 /tmp/zookeeper/ 目錄即可),操作方法如下:

forhappy@haiping-ict:/tmp$ pwd /tmp forhappy@haiping-ict:/tmp$ tar xvf zookeeper-3.4.0-pseudoclusters.tar.bz2 forhappy@haiping-ict:/tmp$ cd zookeeper/ forhappy@haiping-ict:/tmp/zookeeper$ ls server001 server003 server005 stopZKCluster.sh server002 server004 startZKCluster.sh

然后在 /tmp/zookeeper 目錄下執(zhí)行 startZKCluster.sh 啟動(dòng) Zookeeper 服務(wù),或者執(zhí)行 stopZKCluster.sh 停掉 Zookeeper 服務(wù)。

啟動(dòng) Zookeeper 服務(wù):

forhappy@haiping-ict:/tmp/zookeeper$ ./startZKCluster.sh . starting zookeeper instance server001... JMX enabled by default Using config: /tmp/zookeeper/server001/zookeeper-3.4.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED starting zookeeper instance server002... JMX enabled by default Using config: /tmp/zookeeper/server002/zookeeper-3.4.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED starting zookeeper instance server003... JMX enabled by default Using config: /tmp/zookeeper/server003/zookeeper-3.4.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED starting zookeeper instance server004... JMX enabled by default Using config: /tmp/zookeeper/server004/zookeeper-3.4.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED starting zookeeper instance server005... JMX enabled by default Using config: /tmp/zookeeper/server005/zookeeper-3.4.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED

停掉 Zookeeper 服務(wù):

forhappy@haiping-ict:/tmp/zookeeper$ ./stopZKCluster.sh . stopping zookeeper instance server001... JMX enabled by default Using config: /tmp/zookeeper/server001/zookeeper-3.4.0/bin/../conf/zoo.cfg Stopping zookeeper ... STOPPED stopping zookeeper instance server002... JMX enabled by default Using config: /tmp/zookeeper/server002/zookeeper-3.4.0/bin/../conf/zoo.cfg Stopping zookeeper ... STOPPED stopping zookeeper instance server003... JMX enabled by default Using config: /tmp/zookeeper/server003/zookeeper-3.4.0/bin/../conf/zoo.cfg Stopping zookeeper ... STOPPED stopping zookeeper instance server004... JMX enabled by default Using config: /tmp/zookeeper/server004/zookeeper-3.4.0/bin/../conf/zoo.cfg Stopping zookeeper ... STOPPED stopping zookeeper instance server005... JMX enabled by default Using config: /tmp/zookeeper/server005/zookeeper-3.4.0/bin/../conf/zoo.cfg Stopping zookeeper ... STOPPED

Zookeeper C API 安裝

Zookeeper C client 的實(shí)現(xiàn)在 src/c 目錄下,進(jìn)入到該目錄安裝 Zookeeper C client,步驟如下:

$ ./configure $ make $ sudo make install

至此,基本的準(zhǔn)備工作已經(jīng)完成,你可以通過(guò) Zookeeper 本身提供的 Shell 來(lái)操作 Zookeeper,操作方法如下,進(jìn)入 /tmp/zookeeper/server001/zookeeper-3.4.0 目錄,執(zhí)行bin/zkCli.sh -server 127.0.0.1:2181 進(jìn)入 Zookeeper shell:

forhappy@haiping-ict:/tmp/zookeeper/server001/zookeeper-3.4.0$ bin/zkCli.sh -server 127.0.0.1:2181 [zk: 127.0.0.1:2181(CONNECTED) 2] help ZooKeeper -server host:port cmd argsconnect host:portget path [watch]ls path [watch]set path data [version]rmr pathdelquota [-n|-b] pathquit printwatches on|offcreate [-s] [-e] path data aclstat path [watch]close ls2 path [watch]history listquota pathsetAcl path aclgetAcl pathsync pathredo cmdnoaddauth scheme authdelete path [version]setquota -n|-b val path

在 shell 中你可以完成基本的操作,如創(chuàng)建、獲取、刪除、設(shè)置某一節(jié)點(diǎn),設(shè)置節(jié)點(diǎn) ACL等,可以 zookeeper shell 中通過(guò) help 獲取相關(guān)命令的用法。

如果你按照上面的步驟完成了 Zookeeper 偽分布式的安裝,并且想繼續(xù)了解 Zookeeper C API 的使用方法,請(qǐng)繼續(xù)閱讀《Zookeeper C API 指南二(監(jiān)視(Wathes), 基本常量和結(jié)構(gòu)體介紹)》


接上一篇《Zookeeper C API 指南一(準(zhǔn)備工作)》,本問(wèn)將重點(diǎn)介紹 Zookeeper 監(jiān)視(Watches),以及 Zookeeper C API 中基本的常量與結(jié)構(gòu)體。

Zookeeper 監(jiān)視(Watches) 簡(jiǎn)介

Zookeeper C API 的聲明和描述在 include/zookeeper.h 中可以找到,另外大部分的 Zookeeper C API 常量、結(jié)構(gòu)體聲明也在 zookeeper.h 中,如果如果你在使用 C API 是遇到不明白的地方,最好看看 zookeeper.h,或者自己使用 doxygen 生成 Zookeeper C API 的幫助文檔。

Zookeeper 中最有特色且最不容易理解的是監(jiān)視(Watches)。Zookeeper 所有的讀操作——getData(),getChildren(), 和 exists() 都 可以設(shè)置監(jiān)視(watch),監(jiān)視事件可以理解為一次性的觸發(fā)器, 官方定義如下: a watch event is one-time trigger, sent to the client that set the watch, which occurs when the data for which the watch was set changes。對(duì)此需要作出如下理解:

  • (一次性觸發(fā))One-time trigger

    當(dāng)設(shè)置監(jiān)視的數(shù)據(jù)發(fā)生改變時(shí),該監(jiān)視事件會(huì)被發(fā)送到客戶端,例如,如果客戶端調(diào)用了 getData("/znode1", true) 并且稍后 /znode1 節(jié)點(diǎn)上的數(shù)據(jù)發(fā)生了改變或者被刪除了,客戶端將會(huì)獲取到 /znode1 發(fā)生變化的監(jiān)視事件,而如果 /znode1 再一次發(fā)生了變化,除非客戶端再次對(duì) /znode1 設(shè)置監(jiān)視,否則客戶端不會(huì)收到事件通知。

  • (發(fā)送至客戶端)Sent to the client

    Zookeeper 客戶端和服務(wù)端是通過(guò) socket 進(jìn)行通信的,由于網(wǎng)絡(luò)存在故障,所以監(jiān)視事件很有可能不會(huì)成功地到達(dá)客戶端,監(jiān)視事件是異步發(fā)送至監(jiān)視者的,Zookeeper 本身提供了保序性(ordering guarantee):即客戶端只有首先看到了監(jiān)視事件后,才會(huì)感知到它所設(shè)置監(jiān)視的 znode 發(fā)生了變化(a client will never see a change for which it has set a watch until it first sees the watch event). 網(wǎng)絡(luò)延遲或者其他因素可能導(dǎo)致不同的客戶端在不同的時(shí)刻感知某一監(jiān)視事件,但是不同的客戶端所看到的一切具有一致的順序。

  • (被設(shè)置 watch 的數(shù)據(jù))The data for which the watch was set

    這意味著 znode 節(jié)點(diǎn)本身具有不同的改變方式。你也可以想象 Zookeeper 維護(hù)了兩條監(jiān)視鏈表:數(shù)據(jù)監(jiān)視和子節(jié)點(diǎn)監(jiān)視(data watches and child watches) getData() and exists() 設(shè)置數(shù)據(jù)監(jiān)視,getChildren() 設(shè)置子節(jié)點(diǎn)監(jiān)視。 或者,你也可以想象 Zookeeper 設(shè)置的不同監(jiān)視返回不同的數(shù)據(jù),getData() 和 exists() 返回 znode 節(jié)點(diǎn)的相關(guān)信息,而 getChildren() 返回子節(jié)點(diǎn)列表。因此, setData() 會(huì)觸發(fā)設(shè)置在某一節(jié)點(diǎn)上所設(shè)置的數(shù)據(jù)監(jiān)視(假定數(shù)據(jù)設(shè)置成功),而一次成功的 create() 操作則會(huì)出發(fā)當(dāng)前節(jié)點(diǎn)上所設(shè)置的數(shù)據(jù)監(jiān)視以及父節(jié)點(diǎn)的子節(jié)點(diǎn)監(jiān)視。一次成功的 delete() 操作將會(huì)觸發(fā)當(dāng)前節(jié)點(diǎn)的數(shù)據(jù)監(jiān)視和子節(jié)點(diǎn)監(jiān)視事件,同時(shí)也會(huì)觸發(fā)該節(jié)點(diǎn)父節(jié)點(diǎn)的child watch。

Zookeeper 中的監(jiān)視是輕量級(jí)的,因此容易設(shè)置、維護(hù)和分發(fā)。當(dāng)客戶端與 Zookeeper 服務(wù)器端失去聯(lián)系時(shí),客戶端并不會(huì)收到監(jiān)視事件的通知,只有當(dāng)客戶端重新連接后,若在必要的情況下,以前注冊(cè)的監(jiān)視會(huì)重新被注冊(cè)并觸發(fā),對(duì)于開(kāi)發(fā)人員來(lái)說(shuō) 這通常是透明的。只有一種情況會(huì)導(dǎo)致監(jiān)視事件的丟失,即:通過(guò) exists() 設(shè)置了某個(gè) znode 節(jié)點(diǎn)的監(jiān)視,但是如果某個(gè)客戶端在此 znode 節(jié)點(diǎn)被創(chuàng)建和刪除的時(shí)間間隔內(nèi)與 zookeeper 服務(wù)器失去了聯(lián)系,該客戶端即使稍后重新連接 zookeeper服務(wù)器后也得不到事件通知。

Zookeeper C API 常量與部分結(jié)構(gòu)(struct)介紹

與 ACL 相關(guān)的結(jié)構(gòu)與常量:

struct Id 結(jié)構(gòu)為:

struct Id {char * scheme;char * id; };

struct ACL 結(jié)構(gòu)為:

struct ACL {int32_t perms;struct Id id; };

struct ACL_vector 結(jié)構(gòu)為:

struct ACL_vector {int32_t count;struct ACL *data;};

與 znode 訪問(wèn)權(quán)限有關(guān)的常量

  • const int ZOO_PERM_READ; //允許客戶端讀取 znode 節(jié)點(diǎn)的值以及子節(jié)點(diǎn)列表。

  • const int ZOO_PERM_WRITE;// 允許客戶端設(shè)置 znode 節(jié)點(diǎn)的值。

  • const int ZOO_PERM_CREATE; //允許客戶端在該 znode 節(jié)點(diǎn)下創(chuàng)建子節(jié)點(diǎn)。

  • const int ZOO_PERM_DELETE;//允許客戶端刪除子節(jié)點(diǎn)。

  • const int ZOO_PERM_ADMIN; //允許客戶端執(zhí)行 set_acl()。

  • const int ZOO_PERM_ALL;//允許客戶端執(zhí)行所有操作,等價(jià)與上述所有標(biāo)志的或(OR) 。

與 ACL IDs 相關(guān)的常量

  • struct Id ZOO_ANYONE_ID_UNSAFE; //(‘world’,’anyone’)

  • struct Id ZOO_AUTH_IDS;// (‘a(chǎn)uth’,’’)

三種標(biāo)準(zhǔn)的 ACL

  • struct ACL_vector ZOO_OPEN_ACL_UNSAFE; //(ZOO_PERM_ALL,ZOO_ANYONE_ID_UNSAFE)

  • struct ACL_vector ZOO_READ_ACL_UNSAFE;// (ZOO_PERM_READ, ZOO_ANYONE_ID_UNSAFE)

  • struct ACL_vector ZOO_CREATOR_ALL_ACL; //(ZOO_PERM_ALL,ZOO_AUTH_IDS)

與 Interest 相關(guān)的常量:ZOOKEEPER_WRITE, ZOOKEEPER_READ

這 兩個(gè)常量用于標(biāo)識(shí)感興趣的事件并通知 zookeeper 發(fā)生了哪些事件。Interest 常量可以進(jìn)行組合或(OR)來(lái)標(biāo)識(shí)多種興趣(multiple interests: write, read),這兩個(gè)常量一般用于 zookeeper_interest() 和 zookeeper_process()兩個(gè)函數(shù)中。

與節(jié)點(diǎn)創(chuàng)建相關(guān)的常量:ZOO_EPHEMERAL,?ZOO_SEQUENCE

zoo_create 函數(shù)標(biāo)志,ZOO_EPHEMERAL 用來(lái)標(biāo)識(shí)創(chuàng)建臨時(shí)節(jié)點(diǎn),ZOO_SEQUENCE 用來(lái)標(biāo)識(shí)節(jié)點(diǎn)命名具有遞增的后綴序號(hào)(一般是節(jié)點(diǎn)名稱后填充 10 位字符的序號(hào),如 /xyz0000000000, /xyz0000000001, /xyz0000000002, ...),同樣地,ZOO_EPHEMERAL,?ZOO_SEQUENCE可以組合。

與連接狀態(tài) Stat 相關(guān)的常量

以下常量均與 Zookeeper 連接狀態(tài)有關(guān),他們通常用作監(jiān)視器回調(diào)函數(shù)的參數(shù)。

ZOOAPI const int?ZOO_EXPIRED_SESSION_STATE
ZOOAPI const int?ZOO_AUTH_FAILED_STATE
ZOOAPI const int?ZOO_CONNECTING_STATE
ZOOAPI const int?ZOO_ASSOCIATING_STATE
ZOOAPI const int?ZOO_CONNECTED_STATE

與監(jiān)視類型(Watch Types)相關(guān)的常量

以下常量標(biāo)識(shí)監(jiān)視事件的類型,他們通常用作監(jiān)視器回調(diào)函數(shù)的第一個(gè)參數(shù)。

  • ZOO_CREATED_EVENT; // 節(jié)點(diǎn)被創(chuàng)建(此前該節(jié)點(diǎn)不存在),通過(guò) zoo_exists() 設(shè)置監(jiān)視。
  • ZOO_DELETED_EVENT; // 節(jié)點(diǎn)被刪除,通過(guò) zoo_exists() 和 zoo_get() 設(shè)置監(jiān)視。
  • ZOO_CHANGED_EVENT; // 節(jié)點(diǎn)發(fā)生變化,通過(guò) zoo_exists() 和 zoo_get() 設(shè)置監(jiān)視。
  • ZOO_CHILD_EVENT; // 子節(jié)點(diǎn)事件,通過(guò)zoo_get_children() 和 zoo_get_children2()設(shè)置監(jiān)視。
  • ZOO_SESSION_EVENT; // 會(huì)話丟失
  • ZOO_NOTWATCHING_EVENT; // 監(jiān)視被移除。

Zookeeper C API 錯(cuò)誤碼介紹 ZOO_ERRORS

ZOK?

正常返回

ZSYSTEMERROR?

系統(tǒng)或服務(wù)器端錯(cuò)誤(System and server-side errors),服務(wù)器不會(huì)拋出該錯(cuò)誤,該錯(cuò)誤也只是用來(lái)標(biāo)識(shí)錯(cuò)誤范圍的,即大于該錯(cuò)誤值,且小于 ZAPIERROR 都是系統(tǒng)錯(cuò)誤。

ZRUNTIMEINCONSISTENCY?

運(yùn)行時(shí)非一致性錯(cuò)誤。

ZDATAINCONSISTENCY?

數(shù)據(jù)非一致性錯(cuò)誤。

ZCONNECTIONLOSS?

Zookeeper 客戶端與服務(wù)器端失去連接

ZMARSHALLINGERROR?

marshallingunmarshalling 數(shù)據(jù)時(shí)出現(xiàn)錯(cuò)誤(Error while marshalling or unmarshalling data)

ZUNIMPLEMENTED?

該操作未實(shí)現(xiàn)(Operation is unimplemented)

ZOPERATIONTIMEOUT?

該操作超時(shí)(Operation timeout)

ZBADARGUMENTS?

非法參數(shù)錯(cuò)誤(Invalid arguments)

ZINVALIDSTATE?

非法句柄狀態(tài)(Invliad zhandle state)

ZAPIERROR?

API 錯(cuò)誤(API errors),服務(wù)器不會(huì)拋出該錯(cuò)誤,該錯(cuò)誤也只是用來(lái)標(biāo)識(shí)錯(cuò)誤范圍的,錯(cuò)誤值大于該值的標(biāo)識(shí) API 錯(cuò)誤,而小于該值的標(biāo)識(shí) ZSYSTEMERROR。

ZNONODE?

節(jié)點(diǎn)不存在(Node does not exist)

ZNOAUTH?

沒(méi)有經(jīng)過(guò)授權(quán)(Not authenticated)

ZBADVERSION?

版本沖突(Version conflict)

ZNOCHILDRENFOREPHEMERALS?

臨時(shí)節(jié)點(diǎn)不能擁有子節(jié)點(diǎn)(Ephemeral nodes may not have children)

ZNODEEXISTS?

節(jié)點(diǎn)已經(jīng)存在(The node already exists)

ZNOTEMPTY?

該節(jié)點(diǎn)具有自身的子節(jié)點(diǎn)(The node has children)

ZSESSIONEXPIRED?

會(huì)話過(guò)期(The session has been expired by the server)

ZINVALIDCALLBACK?

非法的回調(diào)函數(shù)(Invalid callback specified)

ZINVALIDACL?

非法的ACL(Invalid ACL specified)

ZAUTHFAILED?

客戶端授權(quán)失敗(Client authentication failed)

ZCLOSING?

Zookeeper 連接關(guān)閉(ZooKeeper is closing)

ZNOTHING?

并非錯(cuò)誤,客戶端不需要處理服務(wù)器的響應(yīng)(not error, no server responses to process)

ZSESSIONMOVED?

會(huì)話轉(zhuǎn)移至其他服務(wù)器,所以操作被忽略(session moved to another server, so operation is ignored)

?

至此,Zookeeper C API 中的大部分的常量和結(jié)構(gòu)體均已介紹完畢,下一節(jié)《Zookeeper C API 指南三(回調(diào)函數(shù))》將介紹 Zookeeper C API 中的回調(diào)函數(shù)。

接上一篇《Zookeeper C API 指南二(監(jiān)視(Wathes), 基本常量和結(jié)構(gòu)體介紹)》,本文重點(diǎn)介紹 Zookeeper C API 中的各種回調(diào)函數(shù)。

Zookeeper C API 中各種回調(diào)函數(shù)簡(jiǎn)介

在具體介紹 Zookeeper C API 之前,首先介紹一下 Zookeeper C API 中的各種回調(diào)函數(shù)的原型:

監(jiān)視函數(shù)(watch function)原型

typedef void (*watcher_fn)(zhandle_t *zh, int type, int state, const char *path,void *watcherCtx);

?監(jiān)視函數(shù)原型的各個(gè)參數(shù)解釋如下:

zhzookeeper 句柄(handle)
type事件類型(event type). *_EVENT 常量之一.
state連接狀態(tài)(connection state). 狀態(tài)值為 *_STATE 常量之一.
path觸發(fā)監(jiān)視事件的 znode 節(jié)點(diǎn)的路徑,若為 NULL,則事件類型為 ZOO_SESSION_EVENT
watcherCtx監(jiān)視器上下文(watcher context).

其他回調(diào)函數(shù)的原型

Zookeeper 中還有幾種在異步 API(一般以 zoo_a*開(kāi)頭的函數(shù)) 中使用的回調(diào)函數(shù),根據(jù)回調(diào)函數(shù)處理異步函數(shù)返回值類型的不同分為以下幾類:處理返回 void 類型的回調(diào)函數(shù),處理返回 Stat 結(jié)構(gòu)的回調(diào)函數(shù),處理返回字符串的回調(diào)函數(shù),處理返回?cái)?shù)據(jù)的回調(diào)函數(shù),處理返回字符串列表(a list of string)的回調(diào)函數(shù),同時(shí)處理返回字符串列表(a list of string)和 Stat 結(jié)構(gòu)的回調(diào)函數(shù),以及處理返回 ACL 信息的回調(diào)函數(shù),它們分別如下:

// 處理返回 void 類型的回調(diào)函數(shù) typedef void(* void_completion_t)(int rc, const void *data);// 處理返回 Stat 結(jié)構(gòu)的回調(diào)函數(shù) typedef void(* stat_completion_t)(int rc, const struct Stat *stat, const void *data); // 處理返回字符串的回調(diào)函數(shù) typedef void(* string_completion_t)(int rc, const char *value, const void *data); // 處理返回?cái)?shù)據(jù)的回調(diào)函數(shù) typedef void(* data_completion_t)(int rc, const char *value, int value_len, const struct Stat *stat, const void *data); // 處理返回字符串列表(a list of string)的回調(diào)函數(shù) typedef void(* strings_completion_t)(int rc, const struct String_vector *strings, const void *data); // 同時(shí)處理返回字符串列表(a list of string)和 Stat 結(jié)構(gòu)的回調(diào)函數(shù) typedef void(* strings_stat_completion_t)(int rc, const struct String_vector *strings, const struct Stat *stat, const void *data); // 處理以及返回 ACL 信息的回調(diào)函數(shù) typedef void(* acl_completion_t)(int rc, struct ACL_vector *acl, struct Stat *stat, const void *data);

?下面一一介紹上述幾種回調(diào)函數(shù)的用法:

  • 處理返回 void 類型的回調(diào)函數(shù)
typedef void(* void_completion_t)(int rc, const void *data)

該回調(diào)函數(shù)一般在異步 API 調(diào)用結(jié)束或 Zookeeper? 客戶端失去連接時(shí)被調(diào)用。

rc異步函數(shù)調(diào)用返回的錯(cuò)誤碼,連接丟失/超時(shí)將觸發(fā)該原型函數(shù)(此處指具有該函數(shù)原型的回調(diào)函數(shù),下同)的調(diào)用,并且錯(cuò)誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務(wù)器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時(shí);而與數(shù)據(jù)相關(guān)的事件也會(huì)觸發(fā)該原型函數(shù)的調(diào)用,同時(shí)置相應(yīng)的錯(cuò)誤碼,具體見(jiàn)后文(0 代異步函數(shù)調(diào)用成功)
data由調(diào)用者傳入指針,調(diào)用者可以通過(guò)該指針向回調(diào)函數(shù)傳入自定義的參數(shù),開(kāi)發(fā)人員應(yīng)負(fù)責(zé)此指針?biāo)赶騼?nèi)存的釋放。

?

  • 處理返回 Stat 結(jié)構(gòu)的回調(diào)函數(shù)
typedef void(* stat_completion_t)(int rc, const struct Stat *stat, const void *data)

該函數(shù)一般在異步 API 調(diào)用結(jié)束或 Zookeeper? 客戶端失去連接時(shí)被調(diào)用。

rc異步函數(shù)調(diào)用返回的錯(cuò)誤碼,連接丟失/超時(shí)將觸發(fā)該原型函數(shù)(此處指具有該函數(shù)原型的回調(diào)函數(shù),下同)的調(diào)用,并且錯(cuò)誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務(wù)器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時(shí);而與數(shù)據(jù)相關(guān)的事件也會(huì)觸發(fā)該原型函數(shù)的調(diào)用,同時(shí)置相應(yīng)的錯(cuò)誤碼,具體見(jiàn)后文(0 代異步函數(shù)調(diào)用成功)
stat指向與該 znode 節(jié)點(diǎn)相關(guān)的 Stat 信息,如果返回非 0 值(即異步調(diào)用函數(shù)出錯(cuò)),stat 所指向的區(qū)域是未定義的,開(kāi)發(fā)者不負(fù)責(zé)釋放 stat 所指向的內(nèi)存空間。
data由調(diào)用者傳入指針,調(diào)用者可以通過(guò)該指針向回調(diào)函數(shù)傳入自定義的參數(shù),開(kāi)發(fā)人員應(yīng)負(fù)責(zé)此指針?biāo)赶騼?nèi)存的釋放。

?

  • 處理返回字符串的回調(diào)函數(shù)
typedef void(* string_completion_t)(int rc, const char *value, const void *data)

該函數(shù)一般在異步 API 調(diào)用結(jié)束或 Zookeeper? 客戶端失去連接時(shí)被調(diào)用。

rc異步函數(shù)調(diào)用返回的錯(cuò)誤碼,連接丟失/超時(shí)將觸發(fā)該原型函數(shù)(此處指具有該函數(shù)原型的回調(diào)函數(shù),下同)的調(diào)用,并且錯(cuò)誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務(wù)器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時(shí);而與數(shù)據(jù)相關(guān)的事件也會(huì)觸發(fā)該原型函數(shù)的調(diào)用,同時(shí)置相應(yīng)的錯(cuò)誤碼,具體見(jiàn)后文(0 代異步函數(shù)調(diào)用成功)
value返回的字符串
data由調(diào)用者傳入指針,調(diào)用者可以通過(guò)該指針向回調(diào)函數(shù)傳入自定義的參數(shù),開(kāi)發(fā)人員應(yīng)負(fù)責(zé)此指針?biāo)赶騼?nèi)存的釋放。

?

  • 處理返回?cái)?shù)據(jù)的回調(diào)函數(shù)
typedef void(* data_completion_t)(int rc, const char *value, int value_len, const struct Stat *stat, const void *data)

該函數(shù)一般在異步 API 調(diào)用結(jié)束或 Zookeeper? 客戶端失去連接時(shí)被調(diào)用。

rc異步函數(shù)調(diào)用返回的錯(cuò)誤碼,連接丟失/超時(shí)將觸發(fā)該原型函數(shù)(此處指具有該函數(shù)原型的回調(diào)函數(shù),下同)的調(diào)用,并且錯(cuò)誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務(wù)器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時(shí);而與數(shù)據(jù)相關(guān)的事件也會(huì)觸發(fā)該原型函數(shù)的調(diào)用,同時(shí)置相應(yīng)的錯(cuò)誤碼,具體見(jiàn)后文(0 代異步函數(shù)調(diào)用成功)
value異步調(diào)用的返回值,如果返回非 0 值(即異步調(diào)用函數(shù)出錯(cuò)),value 所指向的區(qū)域是未定義的,開(kāi)發(fā)者不負(fù)責(zé)釋放?value 所指向的內(nèi)存空間。
value_len返回 value 數(shù)據(jù)字節(jié)數(shù)(bytes)
stat指向與該 znode 節(jié)點(diǎn)相關(guān)的 Stat 信息,如果返回非 0 值(即異步調(diào)用函數(shù)出錯(cuò)),stat 所指向的區(qū)域是未定義的,開(kāi)發(fā)者不負(fù)責(zé)釋放 stat 所指向的內(nèi)存空間。
data由調(diào)用者傳入指針,調(diào)用者可以通過(guò)該指針向回調(diào)函數(shù)傳入自定義的參數(shù),開(kāi)發(fā)人員應(yīng)負(fù)責(zé)此指針?biāo)赶騼?nèi)存的釋放。

?

  • 處理返回字符串列表(a list of string)的回調(diào)函數(shù)
typedef void(* strings_completion_t)(int rc, const struct String_vector *strings, const void *data)

該函數(shù)一般在異步 API 調(diào)用結(jié)束或 Zookeeper? 客戶端失去連接時(shí)被調(diào)用。

rc異步函數(shù)調(diào)用返回的錯(cuò)誤碼,連接丟失/超時(shí)將觸發(fā)該原型函數(shù)(此處指具有該函數(shù)原型的回調(diào)函數(shù),下同)的調(diào)用,并且錯(cuò)誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務(wù)器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時(shí);而與數(shù)據(jù)相關(guān)的事件也會(huì)觸發(fā)該原型函數(shù)的調(diào)用,同時(shí)置相應(yīng)的錯(cuò)誤碼,具體見(jiàn)后文(0 代異步函數(shù)調(diào)用成功)
strings指向包含了某 znode 節(jié)點(diǎn)的所有子節(jié)點(diǎn)名稱列表的結(jié)構(gòu),如果返回非 0 值(即異步調(diào)用函數(shù)出錯(cuò)),strings 所指向的區(qū)域是未定義的,開(kāi)發(fā)者不負(fù)責(zé)釋放strings 所指向的內(nèi)存空間。
data由調(diào)用者傳入指針,調(diào)用者可以通過(guò)該指針向回調(diào)函數(shù)傳入自定義的參數(shù),開(kāi)發(fā)人員應(yīng)負(fù)責(zé)此指針?biāo)赶騼?nèi)存的釋放。

?

  • 同時(shí)處理返回字符串列表(a list of string)和 Stat 結(jié)構(gòu)的回調(diào)函數(shù)
typedef void(* strings_stat_completion_t)(int rc, const struct String_vector *strings, const struct Stat *stat, const void *data)

該函數(shù)一般在異步 API 調(diào)用結(jié)束或 Zookeeper? 客戶端失去連接時(shí)被調(diào)用。

rc異步函數(shù)調(diào)用返回的錯(cuò)誤碼,連接丟失/超時(shí)將觸發(fā)該原型函數(shù)(此處指具有該函數(shù)原型的回調(diào)函數(shù),下同)的調(diào)用,并且錯(cuò)誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務(wù)器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時(shí);而與數(shù)據(jù)相關(guān)的事件也會(huì)觸發(fā)該原型函數(shù)的調(diào)用,同時(shí)置相應(yīng)的錯(cuò)誤碼,具體見(jiàn)后文(0 代異步函數(shù)調(diào)用成功)
strings指向包含了某 znode 節(jié)點(diǎn)的所有子節(jié)點(diǎn)名稱列表的結(jié)構(gòu),如果返回非 0 值(即異步調(diào)用函數(shù)出錯(cuò)),strings 所指向的區(qū)域是未定義的,開(kāi)發(fā)者不負(fù)責(zé)釋放strings 所指向的內(nèi)存空間。
stat指向與該 znode 節(jié)點(diǎn)相關(guān)的 Stat 信息,如果返回非 0 值(即異步調(diào)用函數(shù)出錯(cuò)),stat 所指向的區(qū)域是未定義的,開(kāi)發(fā)者不負(fù)責(zé)釋放 stat 所指向的內(nèi)存空間。
data由調(diào)用者傳入的指針,調(diào)用者可以通過(guò)該指針向回調(diào)函數(shù)傳入自定義的參數(shù),開(kāi)發(fā)人員應(yīng)負(fù)責(zé)此指針?biāo)赶騼?nèi)存的釋放。

?

  • 處理返回 ACL 信息的回調(diào)函數(shù)
typedef void(* acl_completion_t)(int rc, struct ACL_vector *acl, struct Stat *stat, const void *data)

該函數(shù)一般在異步 API 調(diào)用結(jié)束或 Zookeeper? 客戶端失去連接時(shí)被調(diào)用。

rc異步函數(shù)調(diào)用返回的錯(cuò)誤碼,連接丟失/超時(shí)將觸發(fā)該原型函數(shù)(此處指具有該函數(shù)原型的回調(diào)函數(shù),下同)的調(diào)用,并且錯(cuò)誤碼為 ZCONNECTIONLOSS --? Zookeeper 客戶端與服務(wù)器端的連接丟失,或者 ZOPERATIONTIMEOUT -- 連接超時(shí);而與數(shù)據(jù)相關(guān)的事件也會(huì)觸發(fā)該原型函數(shù)的調(diào)用,同時(shí)置相應(yīng)的錯(cuò)誤碼,具體見(jiàn)后文(0 代異步函數(shù)調(diào)用成功)
acl指向包含某 znode 節(jié)點(diǎn) ACL 信息的指針,如果返回非 0 值(即異步調(diào)用函數(shù)出錯(cuò)),acl 所指向的區(qū)域是未定義的,開(kāi)發(fā)者不負(fù)責(zé)釋放 acl 所指向的內(nèi)存空間。
stat指向與該 znode 節(jié)點(diǎn)相關(guān)的 Stat 信息,如果返回非 0 值(即異步調(diào)用函數(shù)出錯(cuò)),stat 所指向的區(qū)域是未定義的,開(kāi)發(fā)者不負(fù)責(zé)釋放 stat 所指向的內(nèi)存空間。
data由調(diào)用者傳入的指針,調(diào)用者可以通過(guò)該指針向回調(diào)函數(shù)傳入自定義的參數(shù),開(kāi)發(fā)人員應(yīng)負(fù)責(zé)此指針?biāo)赶騼?nèi)存的釋放。

?

至此,所有的回調(diào)函數(shù)均已介紹完畢,下一節(jié)將介紹 Zookeeper C API 分類和基本 API 的使用,見(jiàn)第四講《Zookeeper C API 指南四(C API 概覽)》

上一節(jié)《Zookeeper C API 指南三(回調(diào)函數(shù))》重點(diǎn)講了 Zookeeper C API 中各種回調(diào)函數(shù)的原型,本節(jié)將切入正題,正式講解 Zookeeper C API。相信大家讀完本文后應(yīng)該對(duì) Zookeeper C API 的使用有一個(gè)比較清晰的認(rèn)識(shí)。

Zookeeper C API 概覽

Zookeeper C API 很規(guī)范,接口很容易記憶,大部分接口均以 zoo_ 開(kāi)頭,只有少量接口以 zookeeper_ 開(kāi)頭,所有的 API 匯總?cè)缦?#xff1a;

void zoo_create_op_init(zoo_op_t * op, const char *path, const char *value,int valuelen, const struct ACL_vector *acl,int flags, char *path_buffer, int path_buffer_len);void zoo_delete_op_init(zoo_op_t * op, const char *path, int version);void zoo_set_op_init(zoo_op_t * op, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);void zoo_check_op_init(zoo_op_t * op, const char *path, int version);ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn,int recv_timeout,const clientid_t * clientid,void *context, int flags);ZOOAPI int zookeeper_close(zhandle_t * zh);ZOOAPI const clientid_t *zoo_client_id(zhandle_t * zh);ZOOAPI int zoo_recv_timeout(zhandle_t * zh);ZOOAPI const void *zoo_get_context(zhandle_t * zh);ZOOAPI void zoo_set_context(zhandle_t * zh, void *context);ZOOAPI watcher_fn zoo_set_watcher(zhandle_t * zh, watcher_fn newFn);ZOOAPI struct sockaddr *zookeeper_get_connected_host(zhandle_t * zh, struct sockaddr*addr,socklen_t * addr_len);ZOOAPI int zookeeper_interest(zhandle_t * zh, int *fd, int *interest,struct timeval *tv);ZOOAPI int zookeeper_process(zhandle_t * zh, int events);ZOOAPI int zoo_state(zhandle_t * zh);ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,string_completion_t completion, const void *data);ZOOAPI int zoo_adelete(zhandle_t * zh, const char *path, int version,void_completion_t completion, const void *data);ZOOAPI int zoo_aexists(zhandle_t * zh, const char *path, int watch,stat_completion_t completion, const void *data);ZOOAPI int zoo_awexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,stat_completion_t completion, const void *data);ZOOAPI int zoo_aget(zhandle_t * zh, const char *path, int watch,data_completion_t completion, const void *data);ZOOAPI int zoo_awget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,data_completion_t completion, const void *data);ZOOAPI int zoo_aset(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version,stat_completion_t completion, const void *data);ZOOAPI int zoo_aget_children(zhandle_t * zh, const char *path,int watch,strings_completion_t completion,const void *data);ZOOAPI int zoo_awget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_completion_t completion,const void *data);ZOOAPI int zoo_aget_children2(zhandle_t * zh, const char *path,int watch,strings_stat_completion_t completion,const void *data);ZOOAPI int zoo_awget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_stat_completion_t completion,const void *data);ZOOAPI int zoo_async(zhandle_t * zh, const char *path,string_completion_t completion, const void *data);ZOOAPI int zoo_aget_acl(zhandle_t * zh, const char *path,acl_completion_t completion, const void *data);ZOOAPI int zoo_aset_acl(zhandle_t * zh, const char *path, int version,struct ACL_vector *acl, void_completion_t,const void *data);ZOOAPI int zoo_amulti(zhandle_t * zh, int count, const zoo_op_t * ops,zoo_op_result_t * results, void_completion_t,const void *data);ZOOAPI const char *zerror(int c);ZOOAPI int zoo_add_auth(zhandle_t * zh, const char *scheme,const char *cert, int certLen,void_completion_t completion, const void *data);ZOOAPI int is_unrecoverable(zhandle_t * zh);ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel);ZOOAPI void zoo_set_log_stream(FILE * logStream);ZOOAPI void zoo_deterministic_conn_order(int yesOrNo);ZOOAPI int zoo_create(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,char *path_buffer, int path_buffer_len);ZOOAPI int zoo_delete(zhandle_t * zh, const char *path, int version);ZOOAPI int zoo_exists(zhandle_t * zh, const char *path, int watch,struct Stat *stat);ZOOAPI int zoo_wexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct Stat *stat);ZOOAPI int zoo_get(zhandle_t * zh, const char *path, int watch,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_wget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_set(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version);ZOOAPI int zoo_set2(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);ZOOAPI int zoo_get_children(zhandle_t * zh, const char *path,int watch, struct String_vector *strings);ZOOAPI int zoo_wget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings);ZOOAPI int zoo_get_children2(zhandle_t * zh, const char *path,int watch, struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_wget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_get_acl(zhandle_t * zh, const char *path,struct ACL_vector *acl, struct Stat *stat);ZOOAPI int zoo_set_acl(zhandle_t * zh, const char *path, int version,const struct ACL_vector *acl);ZOOAPI int zoo_multi(zhandle_t * zh, int count, const zoo_op_t * ops,zoo_op_result_t * results);

除了基本的初始化、銷毀 Zookeeper 句柄(zhandle),設(shè)置日志等級(jí)、日志流以及一些具有輔助功能 API(zerror(), zoo_state()等) 外,Zookeeper C API 大部分接口可以根據(jù)同步和異步特性分為兩類,同步接口以 zoo_* 開(kāi)頭,異步接口以則以 zoo_a* 開(kāi)頭。并且除了 zookeeper_init() 以及與 zoo_multi() 或 zoo_amulti() 批量操作相關(guān)的 zoo_op_t 初始化外,其他的 API 的第一個(gè)參數(shù)均為 zhandle_t * zh, 即 Zookeeper 句柄的指針。

Zookeeper C API 分類

  • 初始化、銷毀 Zookeeper 句柄
ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn,int recv_timeout,const clientid_t * clientid,void *context, int flags);ZOOAPI int zookeeper_close(zhandle_t * zh);
  • 輔助函數(shù)
// 設(shè)置日志等級(jí)、日志流 ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel); ZOOAPI void zoo_set_log_stream(FILE * logStream);ZOOAPI const clientid_t *zoo_client_id(zhandle_t * zh);ZOOAPI int zoo_recv_timeout(zhandle_t * zh);ZOOAPI const void *zoo_get_context(zhandle_t * zh);ZOOAPI void zoo_set_context(zhandle_t * zh, void *context);ZOOAPI watcher_fn zoo_set_watcher(zhandle_t * zh, watcher_fn newFn);ZOOAPI struct sockaddr *zookeeper_get_connected_host(zhandle_t * zh, struct sockaddr*addr,socklen_t * addr_len);ZOOAPI int zookeeper_interest(zhandle_t * zh, int *fd, int *interest,struct timeval *tv);ZOOAPI int zookeeper_process(zhandle_t * zh, int events);ZOOAPI int zoo_state(zhandle_t * zh);ZOOAPI const char *zerror(int c);ZOOAPI int is_unrecoverable(zhandle_t * zh);ZOOAPI void zoo_deterministic_conn_order(int yesOrNo);
  • 與 zoo_multi() 和 zoo_amulti() 批量操作相關(guān)的 zoo_op_t 初始化
void zoo_create_op_init(zoo_op_t * op, const char *path, const char *value,int valuelen, const struct ACL_vector *acl,int flags, char *path_buffer, int path_buffer_len);void zoo_delete_op_init(zoo_op_t * op, const char *path, int version);void zoo_set_op_init(zoo_op_t * op, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);void zoo_check_op_init(zoo_op_t * op, const char *path, int version);
  • Zookeeper C API 同步接口
ZOOAPI int zoo_add_auth(zhandle_t * zh, const char *scheme,const char *cert, int certLen,void_completion_t completion, const void *data);ZOOAPI int zoo_create(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,char *path_buffer, int path_buffer_len);ZOOAPI int zoo_delete(zhandle_t * zh, const char *path, int version);ZOOAPI int zoo_exists(zhandle_t * zh, const char *path, int watch,struct Stat *stat);ZOOAPI int zoo_wexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct Stat *stat);ZOOAPI int zoo_get(zhandle_t * zh, const char *path, int watch,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_wget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_set(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version);ZOOAPI int zoo_set2(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);ZOOAPI int zoo_get_children(zhandle_t * zh, const char *path,int watch, struct String_vector *strings);ZOOAPI int zoo_wget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings);ZOOAPI int zoo_get_children2(zhandle_t * zh, const char *path,int watch, struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_wget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_get_acl(zhandle_t * zh, const char *path,struct ACL_vector *acl, struct Stat *stat);ZOOAPI int zoo_set_acl(zhandle_t * zh, const char *path, int version,const struct ACL_vector *acl);ZOOAPI int zoo_multi(zhandle_t * zh, int count, const zoo_op_t * ops,zoo_op_result_t * results);
  • Zookeeper C API 異步接口
ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,string_completion_t completion, const void *data);ZOOAPI int zoo_adelete(zhandle_t * zh, const char *path, int version,void_completion_t completion, const void *data);ZOOAPI int zoo_aexists(zhandle_t * zh, const char *path, int watch,stat_completion_t completion, const void *data);ZOOAPI int zoo_awexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,stat_completion_t completion, const void *data);ZOOAPI int zoo_aget(zhandle_t * zh, const char *path, int watch,data_completion_t completion, const void *data);ZOOAPI int zoo_awget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,data_completion_t completion, const void *data);ZOOAPI int zoo_aset(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version,stat_completion_t completion, const void *data);ZOOAPI int zoo_aget_children(zhandle_t * zh, const char *path,int watch,strings_completion_t completion,const void *data);ZOOAPI int zoo_awget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_completion_t completion,const void *data);ZOOAPI int zoo_aget_children2(zhandle_t * zh, const char *path,int watch,strings_stat_completion_t completion,const void *data);ZOOAPI int zoo_awget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_stat_completion_t completion,const void *data);ZOOAPI int zoo_async(zhandle_t * zh, const char *path,string_completion_t completion, const void *data);ZOOAPI int zoo_aget_acl(zhandle_t * zh, const char *path,acl_completion_t completion, const void *data);ZOOAPI int zoo_aset_acl(zhandle_t * zh, const char *path, int version,struct ACL_vector *acl, void_completion_t,const void *data);ZOOAPI int zoo_amulti(zhandle_t * zh, int count, const zoo_op_t * ops,zoo_op_result_t * results, void_completion_t,const void *data);

?Zookeeper C API 初體驗(yàn)

有了上面的介紹,下面我們來(lái)看一看如何使簡(jiǎn)單地使用 Zookeeper C API 吧。

在使用 Zookeeper C API 時(shí)應(yīng)注意:

  • 頭文件包含 #include <zookeeper/zookeeper.h>
  • 如果你需要編譯多線程版本客戶端程序,請(qǐng)?zhí)砑泳幾g選項(xiàng) -DTHREADED,同時(shí)鏈接時(shí)應(yīng)鏈接?zookeeper_mt 庫(kù);如果你需要編譯單線程客戶端程序,請(qǐng)不要添加編譯選項(xiàng) -DTHREADED,同時(shí)鏈接時(shí)應(yīng)鏈接?zookeeper_st 庫(kù)。

一個(gè)基本的程序如下(更詳細(xì)的例子可以參看 src/c/src/cli.c):

/** =============================================================================** Filename: zktest.c** Description: zookeeper api testcase.** Created: 02/15/2013 08:48:49 PM** Author: Fu Haiping (forhappy), haipingf@gmail.com* Company: ICT ( Institute Of Computing Technology, CAS )** =============================================================================*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <zookeeper/zookeeper.h> #include <zookeeper/zookeeper_log.h>void zktest_watcher_g(zhandle_t* zh, int type, int state,const char* path, void* watcherCtx) {printf("Something happened.\n");printf("type: %d\n", type);printf("state: %d\n", state);printf("path: %s\n", path);printf("watcherCtx: %s\n", (char *)watcherCtx); }void zktest_dump_stat(const struct Stat *stat) {char tctimes[40];char tmtimes[40];time_t tctime;time_t tmtime;if (!stat) {fprintf(stderr,"null\n");return;}tctime = stat->ctime/1000;tmtime = stat->mtime/1000;ctime_r(&tmtime, tmtimes);ctime_r(&tctime, tctimes);fprintf(stderr, "\tctime = %s\tczxid=%llx\n""\tmtime=%s\tmzxid=%llx\n""\tversion=%x\taversion=%x\n""\tephemeralOwner = %llx\n",tctimes, stat->czxid,tmtimes, stat->mzxid,(unsigned int)stat->version, (unsigned int)stat->aversion,stat->ephemeralOwner); }void zktest_stat_completion(int rc, const struct Stat *stat, const void *data) {fprintf(stderr, "%s: rc = %d Stat:\n", (char*)data, rc);zktest_dump_stat(stat); }void zktest_void_completion(int rc, const void *data) {fprintf(stderr, "[%s]: rc = %d\n", (char*)(data==0?"null":data), rc); }void zktest_string_completion(int rc, const char *name, const void *data) {fprintf(stderr, "[%s]: rc = %d\n", (char*)(data==0?"null":data), rc);if (!rc) {fprintf(stderr, "\tname = %s\n", name);} }int main(int argc, const char *argv[]) {const char* host = "127.0.0.1:2181,127.0.0.1:2182,""127.0.0.1:2183,127.0.0.1:2184,127.0.0.1:2185";int timeout = 30000;zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);zhandle_t* zkhandle = zookeeper_init(host,zktest_watcher_g, timeout, 0, "hello zookeeper.", 0);if (zkhandle == NULL) {fprintf(stderr, "Error when connecting to zookeeper servers...\n");exit(EXIT_FAILURE);}// struct ACL ALL_ACL[] = {{ZOO_PERM_ALL, ZOO_ANYONE_ID_UNSAFE}};// struct ACL_vector ALL_PERMS = {1, ALL_ACL};int ret = zoo_acreate(zkhandle, "/xyz", "hello", 5,&ZOO_OPEN_ACL_UNSAFE, 0 /* ZOO_SEQUENCE */,zktest_string_completion, "acreate");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "acreate");exit(EXIT_FAILURE);}ret = 0;ret = zoo_aexists(zkhandle, "/xyz", 1, zktest_stat_completion, "aexists");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "aexists");exit(EXIT_FAILURE);}ret = 0;// Wait for asynchronous zookeeper call done. getchar();ret = zoo_adelete(zkhandle, "/xyz", -1, zktest_void_completion, "adelete");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "adelete");exit(EXIT_FAILURE);}// Wait for asynchronous zookeeper call done. getchar();zookeeper_close(zkhandle); }

下面簡(jiǎn)單講講這個(gè)程序的結(jié)構(gòu):

  • 首先聲明 host, timeout 變量。
const char* host = "127.0.0.1:2181,127.0.0.1:2182,""127.0.0.1:2183,127.0.0.1:2184,127.0.0.1:2185"; int timeout = 30000;

其中 host 字符串格式為逗號(hào)隔開(kāi)的 IP:PORT對(duì),可以是 Zookeeper 集群中的全部或部分 Zookeeper 實(shí)例的 IP:PORT對(duì),我們?cè)诘谝恢v《準(zhǔn)備工作》中介紹了如何部署一個(gè)偽分布式的集群,上述的 host 就是這些 zookeeper 實(shí)例的IP:PORT對(duì)。

另外 timeout 是 Zookeeper 客戶端連接服務(wù)器的超時(shí)時(shí)間,單位為毫秒,timeout = 30000 說(shuō)明如果 30 秒內(nèi)客戶端沒(méi)有連接上 Zookeeper 服務(wù)則表示連接超時(shí)。

  • 設(shè)置日志等級(jí)。
zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
  • 初始化 Zookeeper 句柄(zhandle_t)。
zhandle_t* zkhandle = zookeeper_init(host,zktest_watcher_g, timeout, 0, "hello zookeeper.", 0);if (zkhandle == NULL) {fprintf(stderr, "Error when connecting to zookeeper servers...\n");exit(EXIT_FAILURE);}

初始化 Zookeeper 句柄 zookeeper_init() 函數(shù)原型如下:

ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn,int recv_timeout,const clientid_t * clientid,void *context, int flags);

各個(gè)參數(shù)解釋如下:

host逗號(hào)隔開(kāi)的 host:port 對(duì), 每個(gè)代表一個(gè) zk server, 例如: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002"
fn全局的監(jiān)視器回調(diào)函數(shù),當(dāng)發(fā)生事件通知時(shí),該函數(shù)會(huì)被調(diào)用。
clientid客戶端嘗試重連的先前會(huì)話的ID,如果不需要重連先前的會(huì)話,則設(shè)置為 0。客戶端可以通過(guò)調(diào)用 zoo_client_id來(lái)訪問(wèn)一個(gè)已經(jīng)連接上的并且有效的會(huì)話ID,如果clientid對(duì)應(yīng)的會(huì)話超時(shí),或者由于某種原因 clientid變?yōu)闊o(wú)效了,那么zookeeper_init 將返回一個(gè)非法的zhandle_t, 通過(guò) zhandle_t 的狀態(tài)可以獲知zookeeper_init 調(diào)用失敗的原因。 (通常為 ZOO_EXPIRED_SESSION_STATE).
context與 zhandle_t 實(shí)例相關(guān)聯(lián)的“上下文對(duì)象”(可以通過(guò)該參數(shù)為 zhandle_t 傳入自定義類型的數(shù)據(jù)),應(yīng)用程序可以通過(guò) zoo_get_context訪問(wèn)它(例如在監(jiān)視器回調(diào)函數(shù)中),當(dāng)然 zookeeper 內(nèi)部沒(méi)有用到該參數(shù),所以 context 可以設(shè)置為 NULL。
flags目前為保留參數(shù),設(shè)置為 0。
  • 創(chuàng)建一個(gè) znode 節(jié)點(diǎn)。
// struct ACL ALL_ACL[] = {{ZOO_PERM_ALL, ZOO_ANYONE_ID_UNSAFE}};// struct ACL_vector ALL_PERMS = {1, ALL_ACL};int ret = zoo_acreate(zkhandle, "/xyz", "hello", 5,&ZOO_OPEN_ACL_UNSAFE, 0 /* ZOO_SEQUENCE */,zktest_string_completion, "acreate");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "acreate");exit(EXIT_FAILURE);}

這里采用異步方式創(chuàng)建 znode 節(jié)點(diǎn),zoo_acreate() 函數(shù)原型為:

ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,string_completion_t completion, const void *data);

各個(gè)參數(shù)解釋如下:

zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
value該節(jié)點(diǎn)保存的數(shù)據(jù)。
valuelen該節(jié)點(diǎn)保存數(shù)據(jù)的大小。
acl該節(jié)點(diǎn)初始 ACL,ACL 不能為null 或空。
flags該參數(shù)可以設(shè)置為 0,或者創(chuàng)建標(biāo)識(shí)符 ZOO_EPHEMERAL,?ZOO_SEQUENCE 的組合或(OR)。
completion當(dāng)創(chuàng)建節(jié)點(diǎn)請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 父節(jié)點(diǎn)不存在;ZNODEEXISTS 節(jié)點(diǎn)已存在;ZNOAUTH 客戶端沒(méi)有權(quán)限創(chuàng)建節(jié)點(diǎn)。ZNOCHILDRENFOREPHEMERALS 臨時(shí)節(jié)點(diǎn)不能創(chuàng)建子節(jié)點(diǎn)。
datacompletino函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。
  • 調(diào)用 exists() 函數(shù),設(shè)置監(jiān)視器。
ret = zoo_aexists(zkhandle, "/xyz", 1, zktest_stat_completion, "aexists");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "aexists");exit(EXIT_FAILURE);}
  • 調(diào)用 delete 函數(shù),刪除 znode 節(jié)點(diǎn)。
ret = zoo_adelete(zkhandle, "/xyz", -1, zktest_void_completion, "adelete");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "adelete");exit(EXIT_FAILURE);}
  • 銷毀 zookeeper 句柄
zookeeper_close(zkhandle);

好了,至此本文大致講完了 Zookeeper C API 的分類和幾個(gè)基本函數(shù)的用法。之所以為 Zookeeper C API 分類是方便記憶,開(kāi)發(fā)者可以迅速找到自己需要的 API;另外,本文還講了幾個(gè)基本函數(shù)的使用方法,包括 zookeeper_init(),zoo_acreate(), zoo_aexists(), zoo_adelete() 以及 zookeeper_close()。相信大家對(duì) Zookeeper C API 也有了一個(gè)大致的了解,第五講我會(huì)給大家介紹 Zookeeper C API 中的同步調(diào)用的函數(shù)(即以 zoo_* 開(kāi)頭的函數(shù)),然后第六講給大家介紹 Zookeeper C API 中的異步調(diào)用的函數(shù)(即以 zoo_a* 開(kāi)頭的函數(shù))。

上一講《Zookeeper C API 指南四(C API 概覽)》講了Zookeeper C API 的分類和幾個(gè)基本函數(shù)的用法,相信大家對(duì) Zookeeper C API 也有了一個(gè)大致的了解,本文我會(huì)給大家介紹 Zookeeper C API 中的同步調(diào)用的函數(shù)(即以 zoo_* 開(kāi)頭的函數(shù))。

Zookeeper C API 中與訪問(wèn) Zookeeper 服務(wù)相關(guān)(比如創(chuàng)建、刪除 znode 節(jié)點(diǎn),獲取子節(jié)點(diǎn),設(shè)置 znode 數(shù)據(jù)等)的同步 API 如下:

ZOOAPI int zoo_add_auth(zhandle_t * zh, const char *scheme,const char *cert, int certLen,void_completion_t completion, const void *data);ZOOAPI int zoo_create(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,char *path_buffer, int path_buffer_len);ZOOAPI int zoo_delete(zhandle_t * zh, const char *path, int version);ZOOAPI int zoo_exists(zhandle_t * zh, const char *path, int watch,struct Stat *stat);ZOOAPI int zoo_wexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct Stat *stat);ZOOAPI int zoo_get(zhandle_t * zh, const char *path, int watch,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_wget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_set(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version);ZOOAPI int zoo_set2(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);ZOOAPI int zoo_get_children(zhandle_t * zh, const char *path,int watch, struct String_vector *strings);ZOOAPI int zoo_wget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings);ZOOAPI int zoo_get_children2(zhandle_t * zh, const char *path,int watch, struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_wget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_get_acl(zhandle_t * zh, const char *path,struct ACL_vector *acl, struct Stat *stat);ZOOAPI int zoo_set_acl(zhandle_t * zh, const char *path, int version,const struct ACL_vector *acl);ZOOAPI int zoo_multi(zhandle_t * zh, int count, const zoo_op_t * ops,zoo_op_result_t * results);

本文將以上同步 API 在此細(xì)分為一下幾類:(1). 創(chuàng)建、刪除 znode 節(jié)點(diǎn),(2). 可設(shè)置 watch 的 API,(3). 訪問(wèn)、設(shè)置節(jié)點(diǎn) ACL 的 API,(4). 批處理 API

  • 創(chuàng)建、刪除 znode 節(jié)點(diǎn)(兩個(gè))
ZOOAPI int zoo_create(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,char *path_buffer, int path_buffer_len);ZOOAPI int zoo_delete(zhandle_t * zh, const char *path, int version);
  • 創(chuàng)建 znode 節(jié)點(diǎn):
ZOOAPI int zoo_create(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,char *path_buffer, int path_buffer_len);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
value該節(jié)點(diǎn)保存的數(shù)據(jù)。
valuelen該節(jié)點(diǎn)保存數(shù)據(jù)的大小。如果 value 被設(shè)置為 NULL(該 znode 節(jié)點(diǎn)不包含數(shù)據(jù)),則 valuelen 應(yīng)該設(shè)置為 -1。
acl該節(jié)點(diǎn)初始 ACL,ACL 不能為null 或空。
flags該參數(shù)可以設(shè)置為 0,或者創(chuàng)建標(biāo)識(shí)符ZOO_EPHEMERAL,?ZOO_SEQUENCE 的組合或(OR)。
path_buffer用于保存返回節(jié)點(diǎn)新路徑(因?yàn)樵O(shè)置了ZOO_SEQUENCE 后 zoo_create 所創(chuàng)建的節(jié)點(diǎn)名稱與參數(shù) path 提供的名稱不同,新的節(jié)點(diǎn)名稱后面填充了序號(hào)),path 字符串以 NULL 結(jié)束。path_buffer 可以設(shè)置為 NULL,此時(shí) path_buffer_len 等于 0。
path_buffer_lenpath_buffer 的長(zhǎng)度,如果新節(jié)點(diǎn)名稱的長(zhǎng)度大于path_buffer_len,則節(jié)點(diǎn)名稱將會(huì)被截?cái)?#xff0c;而服務(wù)器端該節(jié)點(diǎn)的名稱不會(huì)截?cái)唷?/span>
  • 刪除 znode 節(jié)點(diǎn):
ZOOAPI int zoo_delete(zhandle_t * zh, const char *path, int version);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
version節(jié)點(diǎn)的版本號(hào),如果該 znode 節(jié)點(diǎn)的實(shí)際版本號(hào)與該參數(shù)提供的版本號(hào)不一值,則刪除節(jié)點(diǎn)失敗,如果 version 為 -1,則不作版本檢查。

?

  • 可設(shè)置 watch 的 API(exists(兩個(gè)) + get(兩個(gè)) + get_children(四個(gè)) = 八個(gè))
ZOOAPI int zoo_exists(zhandle_t * zh, const char *path, int watch,struct Stat *stat);ZOOAPI int zoo_wexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct Stat *stat);ZOOAPI int zoo_get(zhandle_t * zh, const char *path, int watch,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_wget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,char *buffer, int *buffer_len, struct Stat *stat);ZOOAPI int zoo_get_children(zhandle_t * zh, const char *path,int watch, struct String_vector *strings);ZOOAPI int zoo_wget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings);ZOOAPI int zoo_get_children2(zhandle_t * zh, const char *path,int watch, struct String_vector *strings,struct Stat *stat);ZOOAPI int zoo_wget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings,struct Stat *stat);
  • 檢查節(jié)點(diǎn)狀態(tài) exists(兩個(gè),分別是 zoo_exists() 和 zoo_wexists(),區(qū)別是后者可以指定單獨(dú)的 watcher_fn(監(jiān)視器回調(diào)函數(shù)),而前者只能用 zookeeper_init() 設(shè)置的全局監(jiān)視器回調(diào)函數(shù),同時(shí) get 和 get_children兩族函數(shù)也一樣,帶有zoo_w* 的函數(shù)可以指定單獨(dú)的 watcher_fn)。
ZOOAPI int zoo_exists(zhandle_t * zh, const char *path, int watch, struct Stat *stat);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watch如果非 0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知,即使當(dāng)前指定的節(jié)點(diǎn)不存在也會(huì)設(shè)置監(jiān)視,這樣該節(jié)點(diǎn)被創(chuàng)建時(shí),客戶端也可以得到通知。
stat返回的 Stat 信息。

?

ZOOAPI int zoo_wexists(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx,struct Stat *stat);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watcher如果不為 NULL 則會(huì)在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知,即使當(dāng)前指定的節(jié)點(diǎn)不存在也會(huì)設(shè)置監(jiān)視,這樣該節(jié)點(diǎn)被創(chuàng)建時(shí),客戶端也可以得到通知。
watcherCtx用戶指定的數(shù)據(jù),將被傳入到監(jiān)視器回調(diào)函數(shù)中,與由 zookeeper_init() 設(shè)置的全局監(jiān)視器上下文不同,該函數(shù)設(shè)置的監(jiān)視器上下文只與當(dāng)前的監(jiān)視器相關(guān)聯(lián)。
stat返回的 Stat 信息。

?

  • 獲取節(jié)點(diǎn)數(shù)據(jù) get(兩個(gè))
ZOOAPI int zoo_get(zhandle_t * zh, const char *path, int watch,char *buffer, int *buffer_len, struct Stat *stat);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watch如果非0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知
buffer用于保存從 zookeeper 服務(wù)器獲取的節(jié)點(diǎn)數(shù)據(jù)。
buffer_lenbuffer 大小,一旦成功返回該值將會(huì)被設(shè)置為節(jié)點(diǎn)數(shù)據(jù)的實(shí)際大小,如果節(jié)點(diǎn)的數(shù)據(jù)為空,則數(shù)據(jù)大小為 -1,buffer_len 也為 -1。
stat如果非空,stat 指向的結(jié)構(gòu)將會(huì)保存該節(jié)點(diǎn)的 Stat 信息。

?

ZOOAPI int zoo_wget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,char *buffer, int *buffer_len, struct Stat *stat);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watcher如果不為 NULL 則會(huì)在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知
watcherCtx用戶指定的數(shù)據(jù),將被傳入到監(jiān)視器回調(diào)函數(shù)中,與由 zookeeper_init() 設(shè)置的全局監(jiān)視器上下文不同,該函數(shù)設(shè)置的監(jiān)視器上下文只與當(dāng)前的監(jiān)視器相關(guān)聯(lián)。
buffer用于保存從 zookeeper 服務(wù)器獲取的節(jié)點(diǎn)數(shù)據(jù)。
buffer_lenbuffer 大小,一旦成功返回該值將會(huì)被設(shè)置為節(jié)點(diǎn)數(shù)據(jù)的實(shí)際大小,如果節(jié)點(diǎn)的數(shù)據(jù)為空,則數(shù)據(jù)大小為 -1,buffer_len 也為 -1。
stat如果非空,stat 指向的結(jié)構(gòu)將會(huì)保存該節(jié)點(diǎn)的 Stat 信息。
  • 獲取子節(jié)點(diǎn)列表 get_children(四個(gè))
ZOOAPI int zoo_get_children(zhandle_t * zh, const char *path,int watch, struct String_vector *strings);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watch如果非0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知
strings返回各個(gè)子節(jié)點(diǎn)路徑

?

ZOOAPI int zoo_wget_children(zhandle_t * zh, const char *path, watcher_fn watcher, void *watcherCtx,struct String_vector *strings);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watcher如果不為 NULL 則會(huì)在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知
watcherCtx用戶指定的數(shù)據(jù),將被傳入到監(jiān)視器回調(diào)函數(shù)中,與由 zookeeper_init() 設(shè)置的全局監(jiān)視器上下文不同,該函數(shù)設(shè)置的監(jiān)視器上下文只與當(dāng)前的監(jiān)視器相關(guān)聯(lián)。
strings回各個(gè)子節(jié)點(diǎn)路徑

?

ZOOAPI int zoo_get_children2(zhandle_t * zh, const char *path, int watch, struct String_vector *strings,struct Stat *stat);

該函數(shù)最早出現(xiàn)在 Zookeeper 3.3.0中,該函數(shù)功能與 zoo_get_children() 基本一致,但同時(shí)還會(huì)返回指定節(jié)點(diǎn)的 Stat 信息。

zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watch如果非0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知
strings返回各個(gè)子節(jié)點(diǎn)路徑。
stat返回指定節(jié)點(diǎn)的 Stat 信息。

?

ZOOAPI int zoo_wget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,struct String_vector *strings,struct Stat *stat);

該函數(shù)最早出現(xiàn)在 Zookeeper 3.3.0中,該函數(shù)功能與 zoo_wget_children() 基本一致,但同時(shí)還會(huì)返回指定節(jié)點(diǎn)的 Stat 信息。

zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watcher如果不為 NULL 則會(huì)在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知
watcherCtx用戶指定的數(shù)據(jù),將被傳入到監(jiān)視器回調(diào)函數(shù)中,與由 zookeeper_init() 設(shè)置的全局監(jiān)視器上下文不同,該函數(shù)設(shè)置的監(jiān)視器上下文只與當(dāng)前的監(jiān)視器相關(guān)聯(lián)。
strings返回各個(gè)子節(jié)點(diǎn)路徑。
stat返回指定節(jié)點(diǎn)的 Stat 信息。
  • 訪問(wèn)、設(shè)置節(jié)點(diǎn) ACL (兩個(gè))
ZOOAPI int zoo_get_acl(zhandle_t * zh, const char *path, struct ACL_vector *acl, struct Stat *stat);ZOOAPI int zoo_set_acl(zhandle_t * zh, const char *path, int version, const struct ACL_vector *acl);
  • 獲取節(jié)點(diǎn) ACL 信息
ZOOAPI int zoo_get_acl(zhandle_t * zh, const char *path, struct ACL_vector *acl, struct Stat *stat);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
acl該函數(shù)所返回的指定節(jié)點(diǎn)的 ACL 信息。
stat返回指定節(jié)點(diǎn)的 Stat 信息。
  • 設(shè)置節(jié)點(diǎn) ACL
ZOOAPI int zoo_set_acl(zhandle_t * zh, const char *path, int version, const struct ACL_vector *acl);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
version節(jié)點(diǎn)的版本號(hào)。
acl需要設(shè)置的 ACL 信息。
  • 批處理,即原子性地一次提交多個(gè) Zookeeper 操作。
ZOOAPI int zoo_multi(zhandle_t * zh, int count, const zoo_op_t * ops, zoo_op_result_t * results);
zhzookeeper_init() 返回的 zookeeper 句柄。
count提交操作的個(gè)數(shù)。
ops包含所提交操作數(shù)組。
results包含操作所返回結(jié)果的數(shù)組。

其中 zoo_op_t 是各種操作(創(chuàng)建、刪除節(jié)點(diǎn),設(shè)置節(jié)點(diǎn)數(shù)據(jù)和檢查節(jié)點(diǎn)狀態(tài)四種操作)一個(gè)封裝(聯(lián)合體),定義如下:

typedef struct zoo_op {int type;union {// CREATEstruct {const char *path;const char *data;int datalen;char *buf;int buflen;const struct ACL_vector *acl;int flags;} create_op;// DELETE struct {const char *path;int version;} delete_op;// SETstruct {const char *path;const char *data;int datalen;int version;struct Stat *stat;} set_op;// CHECKstruct {const char *path;int version;} check_op;}; } zoo_op_t;

zoo_op_t 一般由以下四個(gè)函數(shù)初始化:

void zoo_create_op_init(zoo_op_t * op, const char *path, const char *value,int valuelen, const struct ACL_vector *acl,int flags, char *path_buffer, int path_buffer_len);void zoo_delete_op_init(zoo_op_t * op, const char *path, int version);void zoo_set_op_init(zoo_op_t * op, const char *path,const char *buffer, int buflen, int version,struct Stat *stat);void zoo_check_op_init(zoo_op_t * op, const char *path, int version);

zoo_op_result_t 用于保存 zoo_multi 或者 zoo_amulti 返回的其中一個(gè)結(jié)果,定義如下:

typedef struct zoo_op_result {int err;char *value;int valuelen;struct Stat *stat; } zoo_op_result_t;

?

以上內(nèi)容是 Zookeeper? C API 中同步 API 的介紹,如有錯(cuò)誤請(qǐng)留下您的想法和意見(jiàn),本人會(huì)盡快更正;同時(shí),我也將在后面的文章中列舉一些示例來(lái)說(shuō)明上述 API 的用法,如有興趣請(qǐng)繼續(xù)關(guān)注,如果您需要了解 Zookeeper 異步 API,請(qǐng)移步第六講《Zookeeper C API 指南六(異步 API 介紹)》。

上一講《Zookeeper C API 指南五(同步 API 介紹)》講了Zookeeper 同步 API 的分類和相關(guān)解釋,相信大家對(duì) Zookeeper 同步 API 也有了一個(gè)大致的了解,本文我會(huì)給大家介紹 Zookeeper C API 中的異步調(diào)用的函數(shù)(即以 zoo_a* 開(kāi)頭的函數(shù)),本文大致結(jié)構(gòu)與《Zookeeper C API 指南五(同步 API 介紹)》,先匯總 API,然后再分類,并對(duì)每個(gè) API 作出解釋。

在具體講解 Zookeeper 異步 API 之前,首先回顧一下《Zookeeper C API 指南三(回調(diào)函數(shù))》,除了監(jiān)視器回調(diào)函數(shù)以外,還有其他 7 種回調(diào)函數(shù),他們通常在異步 API 調(diào)用結(jié)束或 Zookeeper? 客戶端失去連接時(shí)被調(diào)用。根據(jù)回調(diào)函數(shù)返回參數(shù)(即函數(shù)的輸出參數(shù))的類型不同分為以下幾類:返回 void 類型的回調(diào)函數(shù),返回 Stat 結(jié)構(gòu)的回調(diào)函數(shù),返回字符串的回調(diào)函數(shù),返回?cái)?shù)據(jù)的回調(diào)函數(shù),返回字符串列表(a list of string)的回調(diào)函數(shù),同時(shí)返回字符串列表(a list of string)和 Stat 結(jié)構(gòu)的回調(diào)函數(shù),以及返回 ACL 信息的回調(diào)函數(shù),7 中回調(diào)函數(shù)原型聲明如下:

// 返回 void 類型的回調(diào)函數(shù) typedef void(* void_completion_t)(int rc, const void *data);// 返回 Stat 結(jié)構(gòu)的回調(diào)函數(shù) typedef void(* stat_completion_t)(int rc, const struct Stat *stat, const void *data); // 返回字符串的回調(diào)函數(shù) typedef void(* string_completion_t)(int rc, const char *value, const void *data); // 返回?cái)?shù)據(jù)的回調(diào)函數(shù) typedef void(* data_completion_t)(int rc, const char *value, int value_len, const struct Stat *stat, const void *data); // 返回字符串列表(a list of string)的回調(diào)函數(shù) typedef void(* strings_completion_t)(int rc, const struct String_vector *strings, const void *data); // 同時(shí)返回字符串列表(a list of string)和 Stat 結(jié)構(gòu)的回調(diào)函數(shù) typedef void(* strings_stat_completion_t)(int rc, const struct String_vector *strings, const struct Stat *stat, const void *data); // 以及返回 ACL 信息的回調(diào)函數(shù) typedef void(* acl_completion_t)(int rc, struct ACL_vector *acl, struct Stat *stat, const void *data);

?可能這么說(shuō)還不是很理解,那么我們以異步創(chuàng)建 znode 節(jié)點(diǎn)(zoo_acreate())為例解釋一下:

zoo_acreate函數(shù)原型如下:

ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,string_completion_t completion, const void *data);

其中參數(shù) string_completion_t completion 即返回字符串的回調(diào)函數(shù),那么當(dāng) zoo_acreate 調(diào)用結(jié)束時(shí)將會(huì)觸發(fā) completion 回調(diào)函數(shù)的調(diào)用,同時(shí)傳遞給 completion 的rc 參數(shù)為: ZOK 操作完成;ZNONODE 父節(jié)點(diǎn)不存在;ZNODEEXISTS 節(jié)點(diǎn)已存在;ZNOAUTH 客戶端沒(méi)有權(quán)限創(chuàng)建節(jié)點(diǎn)。ZNOCHILDRENFOREPHEMERALS 臨時(shí)節(jié)點(diǎn)不能創(chuàng)建子節(jié)點(diǎn)。而string_completion_t completion 中 const char *value 參數(shù)即新節(jié)點(diǎn)的路徑名(注:如果 zoo_acreate 設(shè)置了ZOO_EPHEMERAL,則創(chuàng)建節(jié)點(diǎn)成功后,節(jié)點(diǎn)名稱并不是 zoo_acreate 中 path 參數(shù)所指定的名稱,而是類似與 /xyz0000000001,/xyz0000000002... 的名稱)。另外,string_completion_t completion const void *data 參數(shù)即為 zoo_acreate 中的 const void *data。

一般來(lái)說(shuō),zoo_acreate 函數(shù)可以按照以下方式調(diào)用:

int ret = zoo_acreate(zkhandle, "/xyz", "hello", 5,&ZOO_OPEN_ACL_UNSAFE, 0 /* ZOO_SEQUENCE */,zktest_string_completion, "acreate");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "acreate");exit(EXIT_FAILURE);}

?其中 zktest_string_completion 功能很簡(jiǎn)單,就是把創(chuàng)建成功后的節(jié)點(diǎn)名稱打印出來(lái),函數(shù)定義如下:

void zktest_string_completion(int rc, const char *name, const void *data) {fprintf(stderr, "[%s]: rc = %d\n", (char*)(data==0?"null":data), rc);if (!rc) {fprintf(stderr, "\tname = %s\n", name);} }

?好了,有了上面的基礎(chǔ),我們接下來(lái)再來(lái)講講 Zookeeper 異步 API 吧 :-)

Zookeeper C API 中與訪問(wèn) Zookeeper 服務(wù)相關(guān)(比如創(chuàng)建、刪除 znode 節(jié)點(diǎn),獲取子節(jié)點(diǎn),設(shè)置 znode 數(shù)據(jù)等)的異步 API 如下:

ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,string_completion_t completion, const void *data);ZOOAPI int zoo_adelete(zhandle_t * zh, const char *path, int version,void_completion_t completion, const void *data);ZOOAPI int zoo_aexists(zhandle_t * zh, const char *path, int watch,stat_completion_t completion, const void *data);ZOOAPI int zoo_awexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,stat_completion_t completion, const void *data);ZOOAPI int zoo_aget(zhandle_t * zh, const char *path, int watch,data_completion_t completion, const void *data);ZOOAPI int zoo_awget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,data_completion_t completion, const void *data);ZOOAPI int zoo_aset(zhandle_t * zh, const char *path,const char *buffer, int buflen, int version,stat_completion_t completion, const void *data);ZOOAPI int zoo_aget_children(zhandle_t * zh, const char *path,int watch,strings_completion_t completion,const void *data);ZOOAPI int zoo_awget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_completion_t completion,const void *data);ZOOAPI int zoo_aget_children2(zhandle_t * zh, const char *path,int watch,strings_stat_completion_t completion,const void *data);ZOOAPI int zoo_awget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_stat_completion_t completion,const void *data);ZOOAPI int zoo_async(zhandle_t * zh, const char *path,string_completion_t completion, const void *data);ZOOAPI int zoo_aget_acl(zhandle_t * zh, const char *path,acl_completion_t completion, const void *data);ZOOAPI int zoo_aset_acl(zhandle_t * zh, const char *path, int version,struct ACL_vector *acl, void_completion_t,const void *data);ZOOAPI int zoo_amulti(zhandle_t * zh, int count, const zoo_op_t * ops,zoo_op_result_t * results, void_completion_t,const void *data);

本文將以上異步 API 細(xì)分為以下幾類:(1). 創(chuàng)建、刪除 znode 節(jié)點(diǎn),(2). 可設(shè)置 watch 的 API,(3). 訪問(wèn)、設(shè)置節(jié)點(diǎn) ACL 的 API,(4). 異步批處理 API。

  • ?創(chuàng)建、刪除 znode 節(jié)點(diǎn)
ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,string_completion_t completion, const void *data);ZOOAPI int zoo_adelete(zhandle_t * zh, const char *path, int version,void_completion_t completion, const void *data);
  • 創(chuàng)建 znode 節(jié)點(diǎn)
ZOOAPI int zoo_acreate(zhandle_t * zh, const char *path,const char *value, int valuelen,const struct ACL_vector *acl, int flags,string_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
value該節(jié)點(diǎn)保存的數(shù)據(jù)。
valuelen該節(jié)點(diǎn)保存數(shù)據(jù)的大小。
acl該節(jié)點(diǎn)初始 ACL,ACL 不能為null 或空。
flags該參數(shù)可以設(shè)置為 0,或者創(chuàng)建標(biāo)識(shí)符 ZOO_EPHEMERAL,?ZOO_SEQUENCE 的組合或(OR)。
completion當(dāng)創(chuàng)建節(jié)點(diǎn)請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 父節(jié)點(diǎn)不存在;ZNODEEXISTS 節(jié)點(diǎn)已存在;ZNOAUTH 客戶端沒(méi)有權(quán)限創(chuàng)建節(jié)點(diǎn)。ZNOCHILDRENFOREPHEMERALS 臨時(shí)節(jié)點(diǎn)不能創(chuàng)建子節(jié)點(diǎn)。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。
  • 刪除 znode 節(jié)點(diǎn)
ZOOAPI int zoo_adelete(zhandle_t * zh, const char *path, int version,void_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
version期望的節(jié)點(diǎn)版本號(hào),如果真實(shí)的版本號(hào)與期望的版本號(hào)不同則 zoo_delete() 調(diào)用失敗,-1 表示不不檢查版本號(hào)。
completion當(dāng)刪除節(jié)點(diǎn)請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn);ZBADVERSION 版包號(hào)不匹配;ZNOTEMPTY 當(dāng)前節(jié)點(diǎn)存在子節(jié)點(diǎn),不能被刪除。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

  • 可設(shè)置 watch 的 API(exists(兩個(gè)) + get(兩個(gè)) + get_children(四個(gè)) = 八個(gè))
ZOOAPI int zoo_aexists(zhandle_t * zh, const char *path, int watch,stat_completion_t completion, const void *data);ZOOAPI int zoo_awexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,stat_completion_t completion, const void *data);ZOOAPI int zoo_aget(zhandle_t * zh, const char *path, int watch,data_completion_t completion, const void *data);ZOOAPI int zoo_awget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,data_completion_t completion, const void *data);ZOOAPI int zoo_aget_children(zhandle_t * zh, const char *path,int watch,strings_completion_t completion,const void *data);ZOOAPI int zoo_awget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_completion_t completion,const void *data);ZOOAPI int zoo_aget_children2(zhandle_t * zh, const char *path,int watch,strings_stat_completion_t completion,const void *data);ZOOAPI int zoo_awget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_stat_completion_t completion,const void *data);
  • 檢查節(jié)點(diǎn)狀態(tài) exists(兩個(gè),分別是 zoo_aexists() 和 zoo_awexists(),區(qū)別是后者可以指定單獨(dú)的 watcher_fn(監(jiān)視器回調(diào)函數(shù)),而前者只能用 zookeeper_init() 設(shè)置的全局監(jiān)視器回調(diào)函數(shù),同時(shí) aget 和 aget_children兩族函數(shù)也一樣,帶有zoo_w* 的函數(shù)可以指定單獨(dú)的 watcher_fn)。)
ZOOAPI int zoo_aexists(zhandle_t * zh, const char *path, int watch,stat_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watch如果非 0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知,即使當(dāng)前指定的節(jié)點(diǎn)不存在也會(huì)設(shè)置監(jiān)視,這樣該節(jié)點(diǎn)被創(chuàng)建時(shí),客戶端也可以得到通知。
completion當(dāng) zoo_aexists 請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn)。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

ZOOAPI int zoo_awexists(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,stat_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watcher如果非 0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知,即使當(dāng)前指定的節(jié)點(diǎn)不存在也會(huì)設(shè)置監(jiān)視,這樣該節(jié)點(diǎn)被創(chuàng)建時(shí),客戶端也可以得到通知。
watcherCtx用戶指定的數(shù)據(jù),將被傳入到監(jiān)視器回調(diào)函數(shù)中,與由 zookeeper_init() 設(shè)置的全局監(jiān)視器上下文不同,該函數(shù)設(shè)置的監(jiān)視器上下文只與當(dāng)前的監(jiān)視器相關(guān)聯(lián)。
completion當(dāng)zoo_awexists 請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn)。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

  • 獲取節(jié)點(diǎn)數(shù)據(jù) aget(兩個(gè))
ZOOAPI int zoo_aget(zhandle_t * zh, const char *path, int watch,data_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watch如果非 0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知。
completion當(dāng)zoo_aget 請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn)。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

ZOOAPI int zoo_awget(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,data_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watcher如果非 0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知,即使當(dāng)前指定的節(jié)點(diǎn)不存在也會(huì)設(shè)置監(jiān)視,這樣該節(jié)點(diǎn)被創(chuàng)建時(shí),客戶端也可以得到通知。
watcherCtx用戶指定的數(shù)據(jù),將被傳入到監(jiān)視器回調(diào)函數(shù)中,與由 zookeeper_init() 設(shè)置的全局監(jiān)視器上下文不同,該函數(shù)設(shè)置的監(jiān)視器上下文只與當(dāng)前的監(jiān)視器相關(guān)聯(lián)。
completion當(dāng)zoo_awget 請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn)。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

  • 獲取子節(jié)點(diǎn)列表 aget_children (四個(gè))
ZOOAPI int zoo_aget_children(zhandle_t * zh, const char *path,int watch,strings_completion_t completion,const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watch如果非 0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知。
completion當(dāng) zoo_aget_children 請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn)。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

ZOOAPI int zoo_awget_children(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_completion_t completion,const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watcher如果非 0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知,即使當(dāng)前指定的節(jié)點(diǎn)不存在也會(huì)設(shè)置監(jiān)視,這樣該節(jié)點(diǎn)被創(chuàng)建時(shí),客戶端也可以得到通知。
watcherCtx用戶指定的數(shù)據(jù),將被傳入到監(jiān)視器回調(diào)函數(shù)中,與由 zookeeper_init() 設(shè)置的全局監(jiān)視器上下文不同,該函數(shù)設(shè)置的監(jiān)視器上下文只與當(dāng)前的監(jiān)視器相關(guān)聯(lián)。
completion當(dāng)zoo_awget_children 請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn)。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

ZOOAPI int zoo_aget_children2(zhandle_t * zh, const char *path,int watch,strings_stat_completion_t completion,const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watch如果非 0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知。
completion當(dāng) zoo_aget_children2 請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn)。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

ZOOAPI int zoo_awget_children2(zhandle_t * zh, const char *path,watcher_fn watcher, void *watcherCtx,strings_stat_completion_t completion,const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
watcher如果非 0,則在服務(wù)器端設(shè)置監(jiān)視,當(dāng)節(jié)點(diǎn)發(fā)生變化時(shí)客戶端會(huì)得到通知,即使當(dāng)前指定的節(jié)點(diǎn)不存在也會(huì)設(shè)置監(jiān)視,這樣該節(jié)點(diǎn)被創(chuàng)建時(shí),客戶端也可以得到通知。
watcherCtx用戶指定的數(shù)據(jù),將被傳入到監(jiān)視器回調(diào)函數(shù)中,與由 zookeeper_init() 設(shè)置的全局監(jiān)視器上下文不同,該函數(shù)設(shè)置的監(jiān)視器上下文只與當(dāng)前的監(jiān)視器相關(guān)聯(lián)。
completion當(dāng)zoo_awget_children2 請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn)。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

  • 訪問(wèn)、設(shè)置節(jié)點(diǎn) ACL 的 API
ZOOAPI int zoo_aget_acl(zhandle_t * zh, const char *path,acl_completion_t completion, const void *data);ZOOAPI int zoo_aset_acl(zhandle_t * zh, const char *path, int version,struct ACL_vector *acl, void_completion_t,const void *data);
  • 訪問(wèn)節(jié)點(diǎn) ACL
ZOOAPI int zoo_aget_acl(zhandle_t * zh, const char *path,acl_completion_t completion, const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
completion當(dāng) zoo_aget_acl 請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn)。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

  • 設(shè)置節(jié)點(diǎn) ACL
ZOOAPI int zoo_aset_acl(zhandle_t * zh, const char *path, int version,struct ACL_vector *acl, void_completion_t,const void *data);
zhzookeeper_init() 返回的 zookeeper 句柄。
path節(jié)點(diǎn)路徑。
buffer保存需要設(shè)置的 ACL。
buflenbuffer 的長(zhǎng)度。
completion當(dāng) zoo_aset_acl 請(qǐng)求完成時(shí)會(huì)調(diào)用該函數(shù),該函數(shù)原型詳見(jiàn)第三講《回調(diào)函數(shù)》一節(jié)。同時(shí)傳遞給completion的rc參數(shù)為: ZOK 操作完成;ZNONODE 節(jié)點(diǎn)不存在;ZNOAUTH 客戶端沒(méi)有權(quán)限刪除節(jié)點(diǎn);ZINVALIDACL 非法 ACL;ZBADVERSION 版本號(hào)不匹配。
datacompletion 函數(shù)被調(diào)用時(shí),傳遞給 completion 的數(shù)據(jù)。

?

  • 異步批處理 API
ZOOAPI int zoo_amulti(zhandle_t * zh, int count, const zoo_op_t * ops,zoo_op_result_t * results, void_completion_t,const void *data);

異步批處理與同步批處理方式類似見(jiàn)《Zookeeper C API 指南五(同步 API 介紹)》,只是需要額外設(shè)置一個(gè) void_completion_t 回調(diào)函數(shù),在此不再贅述。

?

以上內(nèi)容是 Zookeeper? C API 中異步 API 的介紹,如有錯(cuò)誤請(qǐng)留下您的想法和意見(jiàn),我會(huì)盡快更正;同時(shí),我也將在后面的文章中列舉一些示例來(lái)說(shuō)明上述 API 的用法,如有興趣請(qǐng)繼續(xù)關(guān)注。

在前面的文章中我們講了大部分 Zookeeper? C API,相信大家已經(jīng)知道怎樣使用 Zookeeper? C API了吧。我曾在《Zookeeper C API 指南》系列文章的第四篇《Zookeeper C API 指南四(C API 概覽)》中也 Zookeeper C API 的分為了 5 類,他們分別是:(1)、初始化、銷毀 Zookeeper 句柄,(2)、與 zoo_multi() 和 zoo_amulti() 批量操作相關(guān)的 zoo_op_t 初始化函數(shù),(3)、同步 API,(4)、異步 API,(5)、輔助函數(shù)。其中“(1)、初始化、銷毀 Zookeeper 句柄”已經(jīng)在《Zookeeper C API 指南四(C API 概覽)》中介紹過(guò)了,并且在《Zookeeper C API 指南五(同步 API 介紹)》和《Zookeeper C API 指南六(異步 API 介紹)》中我們又分別講了“同步 API” 和 “異步 API”(其中也簡(jiǎn)單地介紹了一下與 zoo_multi() 和 zoo_amulti() 批量操作相關(guān)的 zoo_op_t 初始化函數(shù)),所以接下來(lái)我們?cè)賮?lái)講講 Zookeeper C API 中的 “輔助函數(shù)”。

我們分類的 Zookeeper C API 中輔助函數(shù)如下:

ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel);ZOOAPI void zoo_set_log_stream(FILE * logStream);ZOOAPI const clientid_t *zoo_client_id(zhandle_t * zh);ZOOAPI int zoo_recv_timeout(zhandle_t * zh);ZOOAPI const void *zoo_get_context(zhandle_t * zh);ZOOAPI void zoo_set_context(zhandle_t * zh, void *context);ZOOAPI watcher_fn zoo_set_watcher(zhandle_t * zh, watcher_fn newFn);ZOOAPI struct sockaddr *zookeeper_get_connected_host(zhandle_t * zh, struct sockaddr*addr,socklen_t * addr_len);ZOOAPI int zookeeper_interest(zhandle_t * zh, int *fd, int *interest,struct timeval *tv);ZOOAPI int zookeeper_process(zhandle_t * zh, int events);ZOOAPI int zoo_state(zhandle_t * zh);ZOOAPI const char *zerror(int c);ZOOAPI int is_unrecoverable(zhandle_t * zh);ZOOAPI void zoo_deterministic_conn_order(int yesOrNo);

下面我們來(lái)講講其中比較常用的幾個(gè)函數(shù)吧 :-)

  • ?設(shè)置日志等級(jí)
ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel);

其中 logLevel 可以是ZOO_LOG_LEVEL_ERROR, ZOO_LOG_LEVEL_WARN,ZOO_LOG_LEVEL_INFO, ZOO_LOG_LEVEL_DEBUG四個(gè)取值。

?

  • 設(shè)置日志流
ZOOAPI void zoo_set_log_stream(FILE * logStream);

Zookeeper C API 默認(rèn)的日志流是標(biāo)準(zhǔn)輸出,可以通過(guò)該函數(shù)設(shè)置 Zookeeper C API的日志流為文件。

?

  • 獲取客戶端的 session id,只有在客戶端的當(dāng)前連接狀態(tài)有效時(shí)才可以。
ZOOAPI const clientid_t *zoo_client_id(zhandle_t * zh);

?

  • 返回當(dāng)前會(huì)話的超時(shí)時(shí)間,只有在客戶端的當(dāng)前連接狀態(tài)有效時(shí)才可以。
ZOOAPI int zoo_recv_timeout(zhandle_t * zh);

?

  • 獲取 Zookeeper 句柄的上下文。
ZOOAPI const void *zoo_get_context(zhandle_t * zh);

?

  • 設(shè)置 Zookeeper 句柄的上下文。
ZOOAPI void zoo_set_context(zhandle_t * zh, void *context);

?

  • 設(shè)置 Zookeeper 句柄的全局監(jiān)視器回調(diào)函數(shù),該函數(shù)返回全局監(jiān)視器的舊回調(diào)函數(shù)。
ZOOAPI watcher_fn zoo_set_watcher(zhandle_t * zh, watcher_fn newFn);

?

  • 返回當(dāng)前 Zookeeper 連接的套接字地址。
ZOOAPI struct sockaddr *zookeeper_get_connected_host(zhandle_t * zh, struct sockaddr*addr,socklen_t * addr_len);

?

  • 獲取當(dāng)前 Zookeeper 連接狀態(tài)。
ZOOAPI int zoo_state(zhandle_t * zh);

?

  • 返回某一錯(cuò)誤碼的字符串表示。
ZOOAPI const char *zerror(int c);

?

  • 檢查當(dāng)前 Zookeeper 連接是否為不可恢復(fù)的,如果不可恢復(fù),則客戶端需要關(guān)閉連接,然后重連。
ZOOAPI int is_unrecoverable(zhandle_t * zh);

?

好了,Zookeeper 大部分的輔助函數(shù)就介紹到這里了,大家可以更多文檔可以在 zookeeper.h 中找到。:-)

前面七講我們基本上介紹完了 Zookeeper C API 的所有內(nèi)容,本文將結(jié)合一個(gè)小例子講講如何在你的實(shí)際項(xiàng)目中使用 Zookeeper 服務(wù)。

設(shè)想如下場(chǎng)景:

假設(shè)程序 A 需要 7* 24 小時(shí)在線對(duì)外提供服務(wù),但是 A 程序在生產(chǎn)環(huán)境下總是不穩(wěn)定,時(shí)常崩潰,不過(guò)幸運(yùn)的是解決方案很簡(jiǎn)單,在 A 程序崩潰以后只需要重啟它就可以了。當(dāng)然如此簡(jiǎn)單的問(wèn)題你可以提出多種解決方案,比方說(shuō)自己實(shí)現(xiàn)一個(gè)服務(wù)程序,每隔一定時(shí)間去輪詢 A 的狀態(tài),如果發(fā)現(xiàn) A 崩潰了,立即重啟它,并向管理人員報(bào)告問(wèn)題。不過(guò)我們并不打算這么做,畢竟本文主題是講 Zookeeper C API 的應(yīng)用,所以我們采用 Zookeeper 服務(wù)來(lái)解決該問(wèn)題。

若采用 Zookeeper 服務(wù)可以按照如下方案解決問(wèn)題,程序 A 在啟動(dòng)時(shí)創(chuàng)建一個(gè)臨時(shí)(ZOO_EPHEMERAL) znode 節(jié)點(diǎn) /A,然后按照正常流程對(duì)外提供服務(wù)。另外監(jiān)控程序?qū)?/A 節(jié)點(diǎn)設(shè)置監(jiān)視,當(dāng) /A 節(jié)點(diǎn)消失(說(shuō)明 A 程序已經(jīng)崩潰)時(shí),重啟 A 程序。假設(shè) A 的名稱是 QueryServer,即對(duì)外提供查詢服務(wù)的程序,具體提供什么查詢服務(wù)由應(yīng)用自身決定,我們這里只是簡(jiǎn)單地模擬一下。QueryServer 在啟動(dòng)時(shí)創(chuàng)建一個(gè) /QueryServer 的臨時(shí)節(jié)點(diǎn)(ZOO_EPHEMERAL),然后,程序 QueryServerd 監(jiān)控 /QueryServer 節(jié)點(diǎn),當(dāng) /QueryServer 節(jié)點(diǎn)消失(說(shuō)明 A 程序已經(jīng)崩潰)時(shí),重啟?QueryServer 程序。

下面是 QueryServer 的實(shí)現(xiàn)代碼:

/** =============================================================================** Filename: QueryServer.c** Description: QueryServer** Created: 02/15/2013 08:48:49 PM** Author: Fu Haiping (forhappy), haipingf@gmail.com* Company: ICT ( Institute Of Computing Technology, CAS )** =============================================================================*/ #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <zookeeper/zookeeper.h> #include <zookeeper/zookeeper_log.h>void QueryServer_watcher_g(zhandle_t* zh, int type, int state,const char* path, void* watcherCtx) {if (type == ZOO_SESSION_EVENT) {if (state == ZOO_CONNECTED_STATE) {printf("[[[QueryServer]]] Connected to zookeeper service successfully!\n");} else if (state == ZOO_EXPIRED_SESSION_STATE) { printf("Zookeeper session expired!\n");}} }void QueryServer_string_completion(int rc, const char *name, const void *data) {fprintf(stderr, "[%s]: rc = %d\n", (char*)(data==0?"null":data), rc);if (!rc) {fprintf(stderr, "\tname = %s\n", name);} }void QueryServer_accept_query() {printf("QueryServer is running...\n"); }int main(int argc, const char *argv[]) {const char* host = "127.0.0.1:2181,127.0.0.1:2182,""127.0.0.1:2183,127.0.0.1:2184,127.0.0.1:2185";int timeout = 30000;zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);zhandle_t* zkhandle = zookeeper_init(host,QueryServer_watcher_g, timeout, 0, "hello zookeeper.", 0);if (zkhandle == NULL) {fprintf(stderr, "Error when connecting to zookeeper servers...\n");exit(EXIT_FAILURE);}// struct ACL ALL_ACL[] = {{ZOO_PERM_ALL, ZOO_ANYONE_ID_UNSAFE}};// struct ACL_vector ALL_PERMS = {1, ALL_ACL};int ret = zoo_acreate(zkhandle, "/QueryServer", "alive", 5,&ZOO_OPEN_ACL_UNSAFE, ZOO_EPHEMERAL,QueryServer_string_completion, "zoo_acreate");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "acreate");exit(EXIT_FAILURE);}do {// 模擬 QueryServer 對(duì)外提供服務(wù).// 為了簡(jiǎn)單起見(jiàn), 我們?cè)诖苏{(diào)用一個(gè)簡(jiǎn)單的函數(shù)來(lái)模擬 QueryServer.// 然后休眠 5 秒,程序主動(dòng)退出(即假設(shè)此時(shí)已經(jīng)崩潰). QueryServer_accept_query();sleep(5);} while(false);zookeeper_close(zkhandle); }

Makefile如下:

all:QueryServerQueryServer:QueryServer.ogcc -L/usr/local/lib/ -lzookeeper_mt -o $@ $^ QueryServer.o:QueryServer.cgcc -DTHREADED -I/usr/local/include/zookeeper -o $@ -c $^.PHONY:cleanclean:rm QueryServer.o QueryServer

?

QueryServerd 代碼如下:

/** =============================================================================** Filename: QueryServerd.c** Description: QueryServer daemon using zookeeper. ** Created: 02/15/2013 08:48:49 PM** Author: Fu Haiping (forhappy), haipingf@gmail.com* Company: ICT ( Institute Of Computing Technology, CAS )** =============================================================================*/ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <zookeeper/zookeeper.h> #include <zookeeper/zookeeper_log.h>void QueryServerd_watcher_global(zhandle_t * zh, int type, int state,const char *path, void *watcherCtx); static void QueryServerd_dump_stat(const struct Stat *stat); void QueryServerd_stat_completion(int rc, const struct Stat *stat,const void *data); void QueryServerd_watcher_awexists(zhandle_t *zh, int type, int state,const char *path, void *watcherCtx); static void QueryServerd_awexists(zhandle_t *zh);void QueryServerd_watcher_global(zhandle_t * zh, int type, int state,const char *path, void *watcherCtx) {if (type == ZOO_SESSION_EVENT) {if (state == ZOO_CONNECTED_STATE) {printf("Connected to zookeeper service successfully!\n");} else if (state == ZOO_EXPIRED_SESSION_STATE) { printf("Zookeeper session expired!\n");}} }static void QueryServerd_dump_stat(const struct Stat *stat) {char tctimes[40];char tmtimes[40];time_t tctime;time_t tmtime;if (!stat) {fprintf(stderr, "null\n");return;}tctime = stat->ctime / 1000;tmtime = stat->mtime / 1000;ctime_r(&tmtime, tmtimes);ctime_r(&tctime, tctimes);fprintf(stderr, "\tctime = %s\tczxid=%llx\n""\tmtime=%s\tmzxid=%llx\n""\tversion=%x\taversion=%x\n""\tephemeralOwner = %llx\n",tctimes, stat->czxid,tmtimes, stat->mzxid,(unsigned int) stat->version, (unsigned int) stat->aversion,stat->ephemeralOwner); }void QueryServerd_stat_completion(int rc, const struct Stat *stat,const void *data) {// fprintf(stderr, "%s: rc = %d Stat:\n", (char *) data, rc);// QueryServerd_dump_stat(stat); }void QueryServerd_watcher_awexists(zhandle_t *zh, int type, int state,const char *path, void *watcherCtx) {if (state == ZOO_CONNECTED_STATE) {if (type == ZOO_DELETED_EVENT) {printf("QueryServer gone away, restart now...\n");// re-exists and set watch on /QueryServer again. QueryServerd_awexists(zh);pid_t pid = fork();if (pid < 0) {fprintf(stderr, "Error when doing fork.\n");exit(EXIT_FAILURE);}if (pid == 0) { /* child process */// 重啟 QueryServer 服務(wù).execl("/tmp/QueryServer/QueryServer", "QueryServer", NULL);exit(EXIT_SUCCESS);}sleep(1); /* sleep 1 second for purpose. */} else if (type == ZOO_CREATED_EVENT) {printf("QueryServer started...\n");}}// re-exists and set watch on /QueryServer again. QueryServerd_awexists(zh); }static void QueryServerd_awexists(zhandle_t *zh) {int ret =zoo_awexists(zh, "/QueryServer",QueryServerd_watcher_awexists,"QueryServerd_awexists.",QueryServerd_stat_completion,"zoo_awexists");if (ret) {fprintf(stderr, "Error %d for %s\n", ret, "aexists");exit(EXIT_FAILURE);} }int main(int argc, const char *argv[]) {const char *host = "127.0.0.1:2181,127.0.0.1:2182,""127.0.0.1:2183,127.0.0.1:2184,127.0.0.1:2185";int timeout = 30000;zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);zhandle_t *zkhandle = zookeeper_init(host,QueryServerd_watcher_global,timeout,0, "QueryServerd", 0);if (zkhandle == NULL) {fprintf(stderr, "Error when connecting to zookeeper servers...\n");exit(EXIT_FAILURE);}QueryServerd_awexists(zkhandle);// Wait for asynchronous zookeeper call done. getchar();zookeeper_close(zkhandle);return 0; }

?

Makefile 如下:

all:QueryServerdQueryServerd:QueryServerd.ogcc -L/usr/local/lib/ -lzookeeper_mt -o $@ $^ QueryServerd.o:QueryServerd.cgcc -g -DTHREADED -I/usr/local/include/zookeeper -o $@ -c $^.PHONY:cleanclean:rm QueryServerd.o QueryServerd

?

首先執(zhí)行 QueryServerd,

forhappy@haiping-ict:/tmp/QueryServerd$ ./QueryServerd Connected to zookeeper service successfully!

然后執(zhí)行 QueryServer,

forhappy@haiping-ict:/tmp/QueryServer$ ./QueryServer QueryServer is running... [[[QueryServer]]] Connected to zookeeper service successfully! [zoo_acreate]: rc = 0name = /QueryServer

可見(jiàn) Queryerver 創(chuàng)建了 /QueryServer 節(jié)點(diǎn),5 秒后 QueryServer 模擬程序崩潰而退出,那么此時(shí)在 QueryServerd 端輸出如下:

Connected to zookeeper service successfully! QueryServer started... # QueryServerd 感知到 QueryServer 已正常啟動(dòng). QueryServer gone away, restart now... # 5 秒鐘后,QueryServer 崩潰,QueryServerd 準(zhǔn)備重啟 QueryServer. QueryServer is running... #?QueryServer 正在運(yùn)行,以下 3 行是 QueryServer 輸出結(jié)果。 [[[QueryServer]]] Connected to zookeeper service successfully! [zoo_acreate]: rc = 0name = /QueryServer QueryServer started... #?QueryServerd 感知到 QueryServer 已正常啟動(dòng). QueryServer gone away, restart now...# 又過(guò)了 5 秒鐘后,QueryServer 崩潰,QueryServerd 準(zhǔn)備重啟 QueryServer. QueryServer is running... #?QueryServer 再次運(yùn)行,以下 3 行是 QueryServer 輸出結(jié)果。 [[[QueryServer]]] Connected to zookeeper service successfully! [zoo_acreate]: rc = 0name = /QueryServer QueryServer started... #?QueryServerd 再次感知到 QueryServer 已正常啟動(dòng),如此反復(fù). QueryServer gone away, restart now... QueryServer is running... [[[QueryServer]]] Connected to zookeeper service successfully! [zoo_acreate]: rc = 0name = /QueryServer QueryServer started...

即 QueryServer 每 5 秒鐘崩潰一次,然后又被 QueryServerd 重啟,模擬了上面的應(yīng)用場(chǎng)景。

好了 Zookeeper C API 的應(yīng)用小示例講完了,可能應(yīng)用場(chǎng)景選取的不好,不過(guò)大致可以一些說(shuō)明問(wèn)題吧,如果你想看 Zookeeper 更貼近現(xiàn)實(shí)的應(yīng)用場(chǎng)景,可以參考淘寶的一篇文章《ZooKeeper典型應(yīng)用場(chǎng)景一覽》和 IBM developerWorks 的一篇博文《分布式服務(wù)框架 Zookeeper -- 管理分布式環(huán)境中的數(shù)據(jù)》。


總結(jié)

以上是生活随笔為你收集整理的Zookeeper C API 指南的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。