史上最便捷搭建 ZooKeeper 服務(wù)器的方法
點(diǎn)擊“程序員面試吧”,選擇“星標(biāo)??”
點(diǎn)擊文末“閱讀原文”解鎖資料!
單機(jī)模式:這種模式一般適用于開發(fā)測(cè)試環(huán)境,一方面我們沒有那么多機(jī)器資源,另外就是平時(shí)的開發(fā)調(diào)試并不需要極好的穩(wěn)定性。
集群模式:一個(gè) ZooKeeper 集群通常由一組機(jī)器組成,一般 3 臺(tái)以上就可以組成一個(gè)可用的 ZooKeeper 集群了。組成 ZooKeeper 集群的每臺(tái)機(jī)器都會(huì)在內(nèi)存中維護(hù)當(dāng)前的服務(wù)器狀態(tài),并且每臺(tái)機(jī)器之間都會(huì)互相保持通信。
偽集群模式:這是一種特殊的集群模式,即集群的所有服務(wù)器都部署在一臺(tái)機(jī)器上。當(dāng)你手頭上有一臺(tái)比較好的機(jī)器,如果作為單機(jī)模式進(jìn)行部署,就會(huì)浪費(fèi)資源,這種情況下,ZooKeeper 允許你在一臺(tái)機(jī)器上通過啟動(dòng)不同的端口來啟動(dòng)多個(gè) ZooKeeper 服務(wù)實(shí)例,以此來以集群的特性來對(duì)外服務(wù)。
領(lǐng)導(dǎo)者(leader):負(fù)責(zé)進(jìn)行投票的發(fā)起和決議,更新系統(tǒng)狀態(tài)。
跟隨者(follower):用于接收客戶端請(qǐng)求并給客戶端返回結(jié)果,在選主過程中進(jìn)行投票。
觀察者(observer):可以接受客戶端連接,將寫請(qǐng)求轉(zhuǎn)發(fā)給 leader,但是observer 不參加投票的過程,只是為了擴(kuò)展系統(tǒng),提高讀取的速度。

層次化的目錄結(jié)構(gòu),命名符合常規(guī)文件系統(tǒng)規(guī)范,類似于 Linux。
每個(gè)節(jié)點(diǎn)在 ZooKeeper 中叫做 Znode,并且其有一個(gè)唯一的路徑標(biāo)識(shí)。
節(jié)點(diǎn) Znode 可以包含數(shù)據(jù)和子節(jié)點(diǎn),但是 EPHEMERAL 類型的節(jié)點(diǎn)不能有子節(jié)點(diǎn)。
Znode 中的數(shù)據(jù)可以有多個(gè)版本,比如某一個(gè)路徑下存有多個(gè)數(shù)據(jù)版本,那么查詢這個(gè)路徑下的數(shù)據(jù)就需要帶上版本。
客戶端應(yīng)用可以在節(jié)點(diǎn)上設(shè)置監(jiān)視器。
節(jié)點(diǎn)不支持部分讀寫,而是一次性完整讀寫。

服務(wù)提供者在啟動(dòng)的時(shí)候,向 ZooKeeper 上的指定節(jié)點(diǎn) /dubbo/${serviceName}/providers 目錄下寫入自己的 URL 地址,這個(gè)操作就完成了服務(wù)的發(fā)布。
服務(wù)消費(fèi)者啟動(dòng)的時(shí)候,訂閱 /dubbo/${serviceName}/providers 目錄下的提供者 URL 地址, 并向 /dubbo/${serviceName} /consumers 目錄下寫入自己的 URL 地址。
由于同一節(jié)點(diǎn)下子節(jié)點(diǎn)名稱不能相同,所以只要在某個(gè)節(jié)點(diǎn)下創(chuàng)建 Znode,創(chuàng)建成功即表明加鎖成功。注冊(cè)監(jiān)聽器監(jiān)聽此 Znode,只要?jiǎng)h除此 Znode 就通知其他客戶端來加鎖。
創(chuàng)建臨時(shí)順序節(jié)點(diǎn):在某個(gè)節(jié)點(diǎn)下創(chuàng)建節(jié)點(diǎn),來一個(gè)請(qǐng)求則創(chuàng)建一個(gè)節(jié)點(diǎn),由于是順序的,所以序號(hào)最小的獲得鎖,當(dāng)釋放鎖時(shí),通知下一序號(hào)獲得鎖。
使用 docker-compose 搭建集群
├── docker-compose.yml
version: '3.4'
services:
zoo1:
image: zookeeper
restart: always
hostname: zoo1
ports:
- 2181:2181
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=0.0.0.0:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
zoo2:
image: zookeeper
restart: always
hostname: zoo2
ports:
- 2182:2181
environment:
ZOO_MY_ID: 2
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=zoo3:2888:3888;2181
zoo3:
image: zookeeper
restart: always
hostname: zoo3
ports:
- 2183:2181
environment:
ZOO_MY_ID: 3
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181
首先需要下載 ZooKeeper。
將其解壓。
進(jìn)入其 conf/ 目錄,將 zoo_sample .cfg 改成 zoo.cfg。
# The number of milliseconds of each tick
# tickTime:CS通信心跳數(shù)
# ZooKeeper 服務(wù)器之間或客戶端與服務(wù)器之間維持心跳的時(shí)間間隔,也就是每個(gè) tickTime 時(shí)間就會(huì)發(fā)送一個(gè)心跳。tickTime以毫秒為單位。
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
# initLimit:LF初始通信時(shí)限
# 集群中的follower服務(wù)器(F)與leader服務(wù)器(L)之間初始連接時(shí)能容忍的最多心跳數(shù)(tickTime的數(shù)量)。
initLimit=5
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
# syncLimit:LF同步通信時(shí)限
# 集群中的follower服務(wù)器與leader服務(wù)器之間請(qǐng)求和應(yīng)答之間能容忍的最多心跳數(shù)(tickTime的數(shù)量)。
syncLimit=2
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
# dataDir:數(shù)據(jù)文件目錄
# ZooKeeper保存數(shù)據(jù)的目錄,默認(rèn)情況下,ZooKeeper將寫數(shù)據(jù)的日志文件也保存在這個(gè)目錄里。
dataDir=/data/soft/zookeeper-3.4.12/data
# dataLogDir:日志文件目錄
# ZooKeeper保存日志文件的目錄。
dataLogDir=/data/soft/zookeeper-3.4.12/logs
# the port at which the clients will connect
# clientPort:客戶端連接端口
# 客戶端連接 ZooKeeper 服務(wù)器的端口,ZooKeeper 會(huì)監(jiān)聽這個(gè)端口,接受客戶端的訪問請(qǐng)求。
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
# 服務(wù)器名稱與地址:集群信息(服務(wù)器編號(hào),服務(wù)器地址,LF通信端口,選舉端口)
# 這個(gè)配置項(xiàng)的書寫格式比較特殊,規(guī)則如下:
# server.N=YYY:A:B
# 其中N表示服務(wù)器編號(hào),YYY表示服務(wù)器的IP地址,A為L(zhǎng)F通信端口,表示該服務(wù)器與集群中的leader交換的信息的端口。B為選舉端口,表示選舉新leader時(shí)服務(wù)器間相互通信的端口(當(dāng)leader掛掉時(shí),其余服務(wù)器會(huì)相互通信,選擇出新的leader)。一般來說,集群中每個(gè)服務(wù)器的A端口都是一樣,每個(gè)服務(wù)器的B端口也是一樣。但是當(dāng)所采用的為偽集群時(shí),IP地址都一樣,只能時(shí)A端口和B端口不一樣。
Welcome to ZooKeeper!
2020-06-01 15:03:52,512 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1025] - Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2020-06-01 15:03:52,576 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@879] - Socket connection established to localhost/127.0.0.1:2181, initiating session
2020-06-01 15:03:52,599 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1299] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x100001140080000, negotiated timeout = 30000
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
[zk: 127.0.0.1:2181(CONNECTED) 0]
[zk: 127.0.0.1:2181(CONNECTED) 10] ls /
[zookeeper]
[zk: 127.0.0.1:2181(CONNECTED) 11] create /zk myData
Created /zk
[zk: 127.0.0.1:2181(CONNECTED) 12] ls /
[zk, zookeeper]
[zk: 127.0.0.1:2181(CONNECTED) 13]
[zk: 127.0.0.1:2181(CONNECTED) 13] get /zk
myData
cZxid = 0x400000008
ctime = Mon Jun 01 15:07:50 CST 2020
mZxid = 0x400000008
mtime = Mon Jun 01 15:07:50 CST 2020
pZxid = 0x400000008
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: 127.0.0.1:2181(CONNECTED) 14] delete /zk
[zk: 127.0.0.1:2181(CONNECTED) 15] ls /
[zookeeper]
從 GitHub 上面拉取項(xiàng)目。
在 ZooKeeper 文件夾中執(zhí)行 docker-compose up 命令。
![]()
資料專區(qū):zookeeper官方中文文檔

Dubbo官方中文文檔共有169頁(yè),包括17個(gè)模塊,從基礎(chǔ)入門講起,幾乎涵蓋了Dubbo所有知識(shí)點(diǎn)。目錄見左圖。點(diǎn)擊文末閱讀原文免費(fèi)領(lǐng)取!
點(diǎn)擊閱讀原文免費(fèi)領(lǐng)??!

