天天看點

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

文章目錄

第1章·Zookeeper概述。

1.1.概述。

1.2·特點

1.3·資料結構。

1.4·應用場景。

1.5·下載下傳位址

第2章·Zookeeper安裝。

2.1·本地模式安裝部署。

2.2·配置參數解讀。

第3章·Zookeeper内部原理。

3.1·選舉機制

3.2·節點類型。

3.3.stat 結構體

3.4·監聽器原理。

3.5·寫資料流程

第4章·Zookeeper實戰。

4.1.分布式安裝部署

4.2·用戶端指令行操作。

4.3API應用

4.3.1eclipse環境搭建.

4.3.2·建立Z00Keeper用戶端。

4.3.3.建立子節點

4.3.4·擷取子節點并監聽

4.3.5·判斷zmode是否存在。

4.4·案例實戰。

監聽伺服器節點動态上下線案例。

第1章 Zookeeper概述

1.1 概述

Zookeeper是一個開源的分布式的,為分布式應用提供協調服務的Apache項目。

Zookeeper從設計模式角度來了解:是一個基于觀察者模式設計的分布式服務管理架構,它負責存儲和管理大家都關心的資料,然後接受觀察者的注冊,一旦這些資料的狀态發生變化,Zookeeper就将負責通知已經在Zookeeper上注冊的那些觀察者做出相應的反應,進而實作叢集中類似Master/Slave管理模式。

Zookeeper=檔案系統+通知機制

1.2 特點

1)Zookeeper:一個上司者(leader),多個跟随者(follower)組成的叢集。

2)Leader負責進行投票的發起和決議,更新系統狀态

3)Follower用于接收客戶請求并向用戶端傳回結果,在選舉Leader過程中參與投票

4)叢集中隻要有半數以上節點存活,Zookeeper叢集就能正常服務。

5)全局資料一緻:每個server儲存一份相同的資料副本,client無論連接配接到哪個server,資料都是一緻的。

6)更新請求順序進行,來自同一個client的更新請求按其發送順序依次執行。

7)資料更新原子性,一次資料更新要麼成功,要麼失敗。

8)實時性,在一定時間範圍内,client能讀到最新資料。

1.3 資料結構

ZooKeeper資料模型的結構與Unix檔案系統很類似,整體上可以看作是一棵樹,每個節點稱做一個ZNode。

很顯然zookeeper叢集自身維護了一套資料結構。這個存儲結構是一個樹形結構,其上的每一個節點,我們稱之為"znode",每一個znode預設能夠存儲1MB的資料,每個ZNode都可以通過其路徑唯一辨別,如圖5-1所示

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-1 資料結構圖

1.4 應用場景

提供的服務包括:分布式消息同步和協調機制、伺服器節點動态上下線、統一配置管理、負載均衡、叢集管理等,如圖5-2,5-3,5-4所示。

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-2 統一配置管理

1)分布式環境下,配置檔案管理和同步是一個常見問題。

(1)一個叢集中,所有節點的配置資訊是一緻的,比如Hadoop叢集。

(2)對配置檔案修改後,希望能夠快速同步到各個節點上。

2)配置管理可交由ZooKeeper實作。

(1)可将配置資訊寫入ZooKeeper上的一個Znode。

(2)各個節點監聽這個Znode。

(3)一旦Znode中的資料被修改,ZooKeeper将通知各個節點。

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-3 軟負載均衡

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-4 叢集管理

1.5 下載下傳位址

1.官網首頁:

https://zookeeper.apache.org/

2.下載下傳截圖,如圖5-5,5-6,5-7所示

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-5 Zookeeper下載下傳(一)

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-6 Zookeeper下載下傳(二)

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-7 Zookeeper下載下傳(三)

第2章 Zookeeper安裝

2.1 本地模式安裝部署

1.安裝前準備

(1)安裝jdk

(2)通過filezilla工具拷貝zookeeper到到linux系統下

(3)解壓到指定目錄

[[email protected] software]$ tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/
           

2.配置修改

将/opt/module/zookeeper-3.4.10/conf這個路徑下的zoo_sample.cfg修改為zoo.cfg;

進入zoo.cfg檔案:vim zoo.cfg

修改dataDir路徑為

dataDir=/opt/module/zookeeper-3.4.10/zkData
           

在/opt/module/zookeeper-3.4.10/這個目錄上建立zkData檔案夾(可以不建立,會自動建立)

[[email protected] zookeeper-3.4.10]$ mkdir zkData
           

3.操作zookeeper

(1)啟動zookeeper

[[email protected] zookeeper-3.4.10]$ bin/zkServer.sh start
           

(2)檢視程序是否啟動

[atguig[email protected] zookeeper-3.4.10]$ jps
4020 Jps
4001 QuorumPeerMain
           

(3)檢視狀态:

[[email protected] zookeeper-3.4.10]$ bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: standalone
           

(4)啟動用戶端:

[[email protected] zookeeper-3.4.10]$ bin/zkCli.sh
           

(5)退出用戶端:

[zk: localhost:2181(CONNECTED) 0] quit
           

(6)停止zookeeper

[[email protected] zookeeper-3.4.10]$ bin/zkServer.sh stop
           

2.2 配置參數解讀

解讀zoo.cfg 檔案中參數含義

1.tickTime:通信心跳數,Zookeeper伺服器心跳時間,機關毫秒。

Zookeeper使用的基本時間,伺服器之間或用戶端與伺服器之間維持心跳的時間間隔,也就是每個tickTime時間就會發送一個心跳,時間機關為毫秒。

它用于心跳機制,并且設定最小的session逾時時間為兩倍心跳時間。(session的最小逾時時間是2*tickTime)

2.initLimit:LF初始通信時限

叢集中的follower跟随者伺服器(F)與leader上司者伺服器(L)之間初始連接配接時能容忍的最多心跳數(tickTime的數量),用它來限定叢集中的Zookeeper伺服器連接配接到Leader的時限。

投票選舉新leader的初始化時間

Follower在啟動過程中,會從Leader同步所有最新資料,然後确定自己能夠對外服務的起始狀态。

Leader允許F在initLimit時間内完成這個工作。

3.syncLimit:LF同步通信時限

叢集中Leader與Follower之間的最大響應時間機關,假如響應超過syncLimit * tickTime,Leader認為Follwer死掉,從伺服器清單中删除Follwer。

在運作過程中,Leader負責與ZK叢集中所有機器進行通信,例如通過一些心跳檢測機制,來檢測機器的存活狀态。

如果L發出心跳包在syncLimit之後,還沒有從F那收到響應,那麼就認為這個F已經不線上了。

4.dataDir:資料檔案目錄+資料持久化路徑

儲存記憶體資料庫快照資訊的位置,如果沒有其他說明,更新的事務日志也儲存到資料庫。

5.clientPort:用戶端連接配接端口

監聽用戶端連接配接的端口

第3章 Zookeeper内部原理

3.1 選舉機制

1)半數機制(Paxos 協定):叢集中半數以上機器存活,叢集可用。是以zookeeper适合裝在奇數台機器上。

2)Zookeeper雖然在配置檔案中并沒有指定master和slave。但是,zookeeper工作時,是有一個節點為leader,其他則為follower,Leader是通過内部的選舉機制臨時産生的。

3)以一個簡單的例子來說明整個選舉的過程。

假設有五台伺服器組成的zookeeper叢集,它們的id從1-5,同時它們都是最新啟動的,也就是沒有曆史資料,在存放資料量這一點上,都是一樣的。假設這些伺服器依序啟動,來看看會發生什麼,如圖5-8所示。

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-8 Zookeeper的選舉機制

(1)伺服器1啟動,此時隻有它一台伺服器啟動了,它發出去的報沒有任何響應,是以它的選舉狀态一直是LOOKING狀态。

(2)伺服器2啟動,它與最開始啟動的伺服器1進行通信,互相交換自己的選舉結果,由于兩者都沒有曆史資料,是以id值較大的伺服器2勝出,但是由于沒有達到超過半數以上的伺服器都同意選舉它(這個例子中的半數以上是3),是以伺服器1、2還是繼續保持LOOKING狀态。

(3)伺服器3啟動,根據前面的理論分析,伺服器3成為伺服器1、2、3中的老大,而與上面不同的是,此時有三台伺服器選舉了它,是以它成為了這次選舉的leader。

(4)伺服器4啟動,根據前面的分析,理論上伺服器4應該是伺服器1、2、3、4中最大的,但是由于前面已經有半數以上的伺服器選舉了伺服器3,是以它隻能接收當小弟的命了。

(5)伺服器5啟動,同4一樣當小弟。

3.2 節點類型

1.Znode有兩種類型

短暫(ephemeral):用戶端和伺服器端斷開連接配接後,建立的節點自己删除

持久(persistent):用戶端和伺服器端斷開連接配接後,建立的節點不删除

2.Znode有四種形式的目錄節點(預設是persistent )

(1)持久化目錄節點(PERSISTENT)

用戶端與zookeeper斷開連接配接後,該節點依舊存在

(2)持久化順序編号目錄節點(PERSISTENT_SEQUENTIAL)

用戶端與zookeeper斷開連接配接後,該節點依舊存在,隻是Zookeeper給該節點名稱進行順序編号

(3)臨時目錄節點(EPHEMERAL)

用戶端與zookeeper斷開連接配接後,該節點被删除

(4)臨時順序編号目錄節點(EPHEMERAL_SEQUENTIAL)

用戶端與zookeeper斷開連接配接後,該節點被删除,隻是Zookeeper給該節點名稱進行順序編号,如圖5-9所示

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-9 Zookeeper節點類型

3.建立znode時設定順序辨別,znode名稱後會附加一個值,順序号是一個單調遞增的計數器,由父節點維護

4.在分布式系統中,順序号可以被用于為所有的事件進行全局排序,這樣用戶端可以通過順序号推斷事件的順序

3.3 stat結構體

1)czxid- 引起這個znode建立的zxid,建立節點的事務的zxid

每次修改ZooKeeper狀态都會收到一個zxid形式的時間戳,也就是ZooKeeper事務ID。

事務ID是ZooKeeper中所有修改總的次序。每個修改都有唯一的zxid,如果zxid1小于zxid2,那麼zxid1在zxid2之前發生。

2)ctime - znode被建立的毫秒數(從1970年開始)

3)mzxid - znode最後更新的zxid

4)mtime - znode最後修改的毫秒數(從1970年開始)

5)pZxid-znode最後更新的子節點zxid

6)cversion - znode子節點變化号,znode子節點修改次數

7)dataversion - znode資料變化号

8)aclVersion - znode通路控制清單的變化号

9)ephemeralOwner- 如果是臨時節點,這個是znode擁有者的session id。如果不是臨時節點則是0。

10)dataLength- znode的資料長度

11)numChildren - znode子節點數量

3.4 監聽器原理

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-10 監聽器原理

1.監聽原理詳解,如圖5-10所示

1)首先要有一個main()線程

2)在main線程中建立Zookeeper用戶端,這時就會建立兩個線程,一個負責網絡連接配接通信(connet),一個負責監聽(listener)。

3)通過connect線程将注冊的監聽事件發送給Zookeeper。

4)在Zookeeper的注冊監聽器清單中将注冊的監聽事件添加到清單中。

5)Zookeeper監聽到有資料或路徑變化,就會将這個消息發送給listener線程。

6)listener線程内部調用了process()方法。

2.常見的監聽

(1)監聽節點資料的變化:

get path [watch]
           

(2)監聽子節點增減的變化

ls path [watch]
           

3.5 寫資料流程

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-11 Zookeeper寫資料流程

ZooKeeper 的寫資料流程主要分為以下幾步,如圖5-11所示:

1)比如 Client 向 ZooKeeper 的 Server1 上寫資料,發送一個寫請求。

2)如果Server1不是Leader,那麼Server1 會把接受到的請求進一步轉發給Leader,因為每個ZooKeeper的Server裡面有一個是Leader。這個Leader 會将寫請求廣播給各個Server,比如Server1和Server2, 各個Server寫成功後就會通知Leader。

3)當Leader收到大多數 Server 資料寫成功了,那麼就說明資料寫成功了。如果這裡三個節點的話,隻要有兩個節點資料寫成功了,那麼就認為資料寫成功了。寫成功之後,Leader會告訴Server1資料寫成功了。

4)Server1會進一步通知 Client 資料寫成功了,這時就認為整個寫操作成功。ZooKeeper 整個寫資料流程就是這樣的。

第4章 Zookeeper實戰

4.1 分布式安裝部署

1.叢集規劃

在hadoop102、hadoop103和hadoop104三個節點上部署Zookeeper。
           

2.解壓安裝

(1)解壓zookeeper安裝包到/opt/module/目錄下

[[email protected] software]$ tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/
           

(2)在/opt/module/zookeeper-3.4.10/這個目錄下建立zkData

mkdir -p zkData
           

(3)重命名/opt/module/zookeeper-3.4.10/conf這個目錄下的zoo_sample.cfg為zoo.cfg

mv zoo_sample.cfg zoo.cfg
           

3.配置zoo.cfg檔案

(1)具體配置

dataDir=/opt/module/zookeeper-3.4.10/zkData
           

增加如下配置

#######################cluster##########################
server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888
server.4=hadoop104:2888:3888
           

(2)配置參數解讀

server.A=B:C:D。

A是一個數字,表示這個是第幾号伺服器;

B是這個伺服器的ip位址;

C是這個伺服器與叢集中的Leader伺服器交換資訊的端口;

D是萬一叢集中的Leader伺服器挂了,需要一個端口來重新進行選舉,選出一個新的Leader,而這個端口就是用來執行選舉時伺服器互相通信的端口。

叢集模式下配置一個檔案myid,這個檔案在dataDir目錄下,這個檔案裡面有一個資料就是A的值,Zookeeper啟動時讀取此檔案,拿到裡面的資料與zoo.cfg裡面的配置資訊比較進而判斷到底是哪個server。

4.叢集操作

(1)在/opt/module/zookeeper-3.4.10/zkData目錄下建立一個myid的檔案

touch myid
           

添加myid檔案,注意一定要在linux裡面建立,在notepad++裡面很可能亂碼

(2)編輯myid檔案

vi myid
           

在檔案中添加與server對應的編号:如2

(3)拷貝配置好的zookeeper到其他機器上

scp -r zookeeper-3.4.10/ [email protected]:/opt/app/
scp -r zookeeper-3.4.10/ [email protected]:/opt/app/
           

并分别修改myid檔案中内容為3、4

(4)分别啟動zookeeper

[[email protected] zookeeper-3.4.10]# bin/zkServer.sh start
[[email protected] zookeeper-3.4.10]# bin/zkServer.sh start
[[email protected] zookeeper-3.4.10]# bin/zkServer.sh start
           

(5)檢視狀态

[[email protected] zookeeper-3.4.10]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: follower
[[email protected] zookeeper-3.4.10]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: leader
[[email protected] zookeeper-3.4.5]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: follower
           

4.2 用戶端指令行操作

表5-1

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

1.啟動用戶端

[[email protected] zookeeper-3.4.10]$ bin/zkCli.sh
           

2.顯示所有操作指令

[zk: localhost:2181(CONNECTED) 1] help
           
大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

3.檢視目前znode中所包含的内容

[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]
           

4.檢視目前節點資料并能看到更新次數等資料

[zk: localhost:2181(CONNECTED) 1] ls2 /
[zookeeper]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
           

5.建立普通節點

[zk: localhost:2181(CONNECTED) 2] create /app1 "hello app1"
Created /app1
[zk: localhost:2181(CONNECTED) 4] create /app1/server101 "192.168.1.101"
Created /app1/server101
           

6.獲得節點的值

[zk: localhost:2181(CONNECTED) 6] get /app1
hello app1
cZxid = 0x20000000a
ctime = Mon Jul 17 16:08:35 CST 2017
mZxid = 0x20000000a
mtime = Mon Jul 17 16:08:35 CST 2017
pZxid = 0x20000000b
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 10
numChildren = 1
[zk: localhost:2181(CONNECTED) 8] get /app1/server101
192.168.1.101
cZxid = 0x20000000b
ctime = Mon Jul 17 16:11:04 CST 2017
mZxid = 0x20000000b
mtime = Mon Jul 17 16:11:04 CST 2017
pZxid = 0x20000000b
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 13
numChildren = 0
           

7.建立短暫節點

[zk: localhost:2181(CONNECTED) 9] create -e /app-emphemeral 8888
           

(1)在目前用戶端是能檢視到的

[zk: localhost:2181(CONNECTED) 10] ls /
[app1, app-emphemeral, zookeeper]
           

(2)退出目前用戶端然後再重新開機用戶端

[zk: localhost:2181(CONNECTED) 12] quit
[[email protected] zookeeper-3.4.10]$ bin/zkCli.sh
           

(3)再次檢視根目錄下短暫節點已經删除

[zk: localhost:2181(CONNECTED) 0] ls /
[app1, zookeeper]
           

8.建立帶序号的節點

(1)先建立一個普通的根節點app2

[zk: localhost:2181(CONNECTED) 11] create /app2 "app2"
           

(2)建立帶序号的節點

[zk: localhost:2181(CONNECTED) 13] create -s /app2/aa 888
Created /app2/aa0000000000
[zk: localhost:2181(CONNECTED) 14] create -s /app2/bb 888
Created /app2/bb0000000001
[zk: localhost:2181(CONNECTED) 15] create -s /app2/cc 888
Created /app2/cc0000000002
           

如果原節點下有1個節點,則再排序時從1開始,以此類推。

[zk: localhost:2181(CONNECTED) 16] create -s /app1/aa 888
Created /app1/aa0000000001
           

9.修改節點資料值

[zk: localhost:2181(CONNECTED) 2] set /app1 999
           

10.節點的值變化監聽

(1)在104主機上注冊監聽/app1節點資料變化

[zk: localhost:2181(CONNECTED) 26] get /app1 watch
           

(2)在103主機上修改/app1節點的資料

[zk: localhost:2181(CONNECTED) 5] set /app1  777
           

(3)觀察104主機收到資料變化的監聽

WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/app1
           

11.節點的子節點變化監聽(路徑變化)

(1)在104主機上注冊監聽/app1節點的子節點變化

[zk: localhost:2181(CONNECTED) 1] ls /app1 watch
[aa0000000001, server101]
           

(2)在103主機/app1節點上建立子節點

[zk: localhost:2181(CONNECTED) 6] create /app1/bb 666
Created /app1/bb
           

(3)觀察104主機收到子節點變化的監聽

WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/app1
           

12.删除節點

[zk: localhost:2181(CONNECTED) 4] delete /app1/bb
           

13.遞歸删除節點

[zk: localhost:2181(CONNECTED) 7] rmr /app2
           

14.檢視節點狀态

[zk: localhost:2181(CONNECTED) 12] stat /app1
cZxid = 0x20000000a
ctime = Mon Jul 17 16:08:35 CST 2017
mZxid = 0x200000018
mtime = Mon Jul 17 16:54:38 CST 2017
pZxid = 0x20000001c
cversion = 4
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 2
           

4.3 API應用

4.3.1 eclipse/idea環境搭建

1.建立一個Maven工程

2.添加pom檔案

<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.apache.logging.log4j</groupId>
		<artifactId>log4j-core</artifactId>
		<version>2.8.2</version>
	</dependency>
	<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
	<dependency>
		<groupId>org.apache.zookeeper</groupId>
		<artifactId>zookeeper</artifactId>
		<version>3.4.10</version>
	</dependency>
</dependencies>
           

3.拷貝log4j.properties檔案到項目根目錄

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
           

4.3.2 建立ZooKeeper用戶端

private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
private static int sessionTimeout = 2000;
private ZooKeeper zkClient = null;

@Before
public void init() throws Exception {

zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
		@Override
		public void process(WatchedEvent event) {
			// 收到事件通知後的回調函數(使用者的業務邏輯)
			System.out.println(event.getType() + "--" + event.getPath());

			// 再次啟動監聽
			try {
				zkClient.getChildren("/", true);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	});
}
           

4.3.3 建立子節點

// 建立子節點
@Test
public void create() throws Exception {
	// 資料的增删改查
	// 參數1:要建立的節點的路徑; 參數2:節點資料 ; 參數3:節點權限 ;參數4:節點的類型
	String nodeCreated = zkClient.create("/eclipse", "hello zk".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
}
           

4.3.4 擷取子節點并監聽

// 擷取子節點
@Test
public void getChildren() throws Exception {
	List<String> children = zkClient.getChildren("/", true);

	for (String child : children) {
		System.out.println(child);
	}

	// 延時阻塞
	Thread.sleep(Long.MAX_VALUE);
}
           

4.3.5 判斷znode是否存在

// 判斷znode是否存在
@Test
public void exist() throws Exception {
	Stat stat = zkClient.exists("/eclipse", false);

	System.out.println(stat == null ? "not exist" : "exist");
}
           

4.4 案例實戰

監聽伺服器節點動态上下線案例

1.需求

某分布式系統中,主節點可以有多台,可以動态上下線,任意一台用戶端都能實時感覺到主節點伺服器的上下線

2.需求分析,如圖5-12所示

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

圖5-12 伺服器動态上下線

3.具體實作

(0)現在叢集上建立/servers節點

[zk: localhost:2181(CONNECTED) 10] create /servers "servers"
Created /servers
           

(1)伺服器端代碼

package com.atguigu.zkcase;
import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;

public class DistributeServer {

private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
private static int sessionTimeout = 2000;
private ZooKeeper zk = null;
private String parentNode = "/servers";

// 建立到zk的用戶端連接配接
public void getConnect() throws IOException{
	
	zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

		@Override
		public void process(WatchedEvent event) {

		}
	});
}

// 注冊伺服器
public void registServer(String hostname) throws Exception{
	String create = zk.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
	
	System.out.println(hostname +" is online "+ create);
}

// 業務功能
public void business(String hostname) throws Exception{
	System.out.println(hostname+" is working ...");
	
	Thread.sleep(Long.MAX_VALUE);
}

public static void main(String[] args) throws Exception {
	// 1擷取zk連接配接
	DistributeServer server = new DistributeServer();
	server.getConnect();
	
	// 2 利用zk連接配接注冊伺服器資訊
	server.registServer(args[0]);
	
	// 3 啟動業務功能
	server.business(args[0]);
}
}
           

(2)用戶端代碼

package com.atguigu.zkcase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

public class DistributeClient {
private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
private static int sessionTimeout = 2000;
private ZooKeeper zk = null;
private String parentNode = "/servers";

// 建立到zk的用戶端連接配接
public void getConnect() throws IOException {
	zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

		@Override
		public void process(WatchedEvent event) {

			// 再次啟動監聽
			try {
				getServerList();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	});
}

// 擷取伺服器清單資訊
public void getServerList() throws Exception {
	
	// 1擷取伺服器子節點資訊,并且對父節點進行監聽
	List<String> children = zk.getChildren(parentNode, true);

    // 2存儲伺服器資訊清單
	ArrayList<String> servers = new ArrayList<>();
	
    // 3周遊所有節點,擷取節點中的主機名稱資訊
	for (String child : children) {
		byte[] data = zk.getData(parentNode + "/" + child, false, null);

		servers.add(new String(data));
	}

    // 4列印伺服器清單資訊
	System.out.println(servers);
}

// 業務功能
public void business() throws Exception {
	System.out.println("client is working ...");
Thread.sleep(Long.MAX_VALUE);
}

public static void main(String[] args) throws Exception {

	// 1擷取zk連接配接
	DistributeClient client = new DistributeClient();
	client.getConnect();

	// 2擷取servers的子節點資訊,從中擷取伺服器資訊清單
	client.getServerList();

	// 3業務程序啟動
	client.business();
}
}
           

啟動用戶端,監視/servers的子節點情況

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

依次啟動兩個服務端,觀察用戶端情況

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

再添加兩個服務端,觀察用戶端情況

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

挂掉一個服務端,觀察用戶端情況

大資料之Zookeeper:zookeeper資料結構、zookeeper安裝、zookeeper内部原理、分布式zookeeper部署、指令行、zookeeper的API、監聽伺服器動态上下線案例

繼續閱讀