工作中使用到了ZooKeeper做集群的管理工具,把ZooKeeper的安裝和配置簡單記錄一下。
首先是下載ZooKeeper,本來沒什么好說的,只是自己疏忽犯了個低級錯誤,應該下載可執行文件的壓縮包apache-zookeeper-x.x.x-bin.tar.gz,我下載成了源碼的apache-zookeeper-x.x.x.tar.gz,結果導致啟動時報錯,找到不主類。

下載完成壓縮之后就可以進行配置了。也可以先建個軟鏈接,如果以后ZooKeeper版本有變化,只要修改軟鏈接即可。
使用%ZK_HOME%來代表ZooKeeper的安裝目錄。
tar -xzvf apache-zookeeper-3.5.6-bin.tar.gz

ZooKeeper有兩種運行模式,一個是集群模式,一個是單機模式。分別配置如下。
1. 集群模式
假設用三台機器來搭建ZooKeeper集群,IP地址為IP1,IP2,IP3
(1) 配置zoo.cfg文件
初次使用ZooKeeper,需要將%ZOO_HOME%/conf目錄下的zoo_sample.cfg文件重命名為zoo.cfg,並且按照如下代碼進行簡單配置:
tickTime=2000 initLimit=10 syncLimit=5 dataDir=/home/zs/zookeeper/zookeeper1/data dataLogDir=/home/zs/zookeeper/zookeeper1/log clientPort=2181 server.1=IP1:2888:3888 server.2=IP2:2888:3888 server.3=IP3:2888:3888
配置參數解釋如下:
a). tickTime:該參數單位是毫秒ms,用於配置ZooKeeper中最小時間單元的長度,很多運行時的時間間隔都是使用tickTime的倍數來表示的。
b). initLimit:該參數要配置一個正整數N,表示tickTime的N倍。用於配置Leader服務器等待Follower啟動,並完成數據同步的時間。Follower服務器在啟動過程中,會與Leader建立連接並完成對數據的同步,從而確定自己對外提供服務的起始狀態。Leader服務器允許Follower在initLimit時間內完成這個工作。
c). syncLimit:該參數要配置一個正整數N,表示tickTime的N倍。用於配置Leader服務器和Follower之間進行心跳檢測的最大延時時間。如果Leader服務器在syncLimit時間內無法獲取到Follower的心跳檢測響應,那么Leader就會認為該Follower已經脫離了和自己的同步。
d). dataDir:用於配置ZooKeeper服務器存儲快照文件的目錄。默認情況下,如果沒有配置參數dataLogDir,那么事務日志也會存儲在這個目錄中。考慮到事務日志的寫性能直接影響ZooKeeper整體的服務能力,因此建議同時通過參數dataLogDir來配置ZooKeeper的事務日志的存儲目錄。
e). dataLogDir:用於配置ZooKeeper服務器存儲事務日志文件的目錄。dataDir和dataLogDir都要確保有讀寫權限。
f). clientPort:用於配置當前服務器對外的服務端口,客戶端會通過該端口和ZooKeeper服務器創建連接。
g). server.id=host:port:port:該參數用於配置組成ZooKeeper集群的機器列表,其中id即為ServerID,與每台服務器myid文件中的數字相對應。同時,在該參數中,會配置兩個端口:第一個端口用於指定Follower服務器與Leader進行運行時通信和數據同步時所使用的端口,第二個端口則專門用於進行Leader選舉過程中的投票通信。在ZooKeeper服務器啟動的時候,其會根據myid文件中配置的ServerID來確定自己是哪台服務器,並使用對應配置的端口來時行啟動。如果在實際使用過程中,需要在同一台服務器上部署多個ZooKeeper實例來構成偽集群的話,那么這些端口都需要配置成不同。
(2) 創建myid文件
在dataDir所配置的目錄下,創建一個名為myid的文件,在該文件的第一行寫上一個數字,即ServerID,和zoo.cfg中當前機器的編號對應上。例如,server.1的myid文件內容就是“1”。要確保每個服務器的myid文件中的數字不同,並且和自己所在機器的zoo.cfg中的server.id=host:port:port的id值一致。id的范圍是1~255。
(3) 重復(1)和(2)步,為所有機器配置zoo.cfg和myid文件。
(4) 啟動ZooKeeper。
bin/zkServer.sh start

有時雖然執行完啟動命令后,顯示STARTED,但ZooKeeper並沒有真正運行,可以對應狀態進行檢測。在執行啟動命令的目錄下會生成Logs目錄,記錄啟動的日志,若未成功啟動,可在Logs目錄查找原因。
(5) 驗證服務器
要驗證服務器有沒有啟動成功,可以telnet到ZooKeeper的端口,然后發送stat命令來驗證
如果出現以下輸出信息,服務器就啟動成功了。

還可以使用zkServer.sh status 命令,查看ZooKeeper服務器的狀態,如下圖所示,說明該服務器是個follower。

驗證服務器時可能出現的問題如下:
a). 如果使用telnet加stat命令驗證,出現“stat is not executed because it is not in the whitelist.”報錯,可以修改一下啟動腳本,把ZooKeeper的指使添加到白名單。
打開zkServer.sh腳本,在 if [ "x$SERVER_JVMFLAGS" != "x" ] 語句上方添加一條語句,把ZooKeeper的指使添加到白名單。
ZOOMAIN="-Dzookeeper.4lw.commands.whitelist=* ${ZOOMAIN}"

b). 如果使用telnet加stat命令驗證,出現“This ZooKeeper instance is not currently serving requests”報錯,其原因就是集群沒有選出來leader,當集群里的結點只剩下一台,或者不足半數時,就會出現這個錯誤提示。 可以把配置集群里其他ZooKeeper服務器啟動,或者查看各服務器之間網絡是否不通。

c). 如果使用zkServer.sh status命令,出現It is probably not running. 有可能是集群中其他服務器沒有開啟。要整個集群都開啟再執行status命令,只開啟一台服務器並驗證會報錯。也有可能是服務器真沒啟來,看查看一下輸出日志。

(6) 關閉服務器
bin/zkServer.sh stop

2. 偽集群模式
ZooKeeper支持在一台服務器上啟動多個ZooKeeper的實例,相互組成一個集群。不需要拷貝多個ZooKeeper的目錄,就是同一個程序目錄下,配置多個zoo.cfg文件即可。
(1) 配置文件
可以在conf目錄下,創建三個配置文件,分別命名為zoo1.cfg、zoo2.cfg、zoo3.cfg,內容分別如下。注意,dataDir和dataLogDir配置不同的目錄,IP地址均為本機的IP地址,但端口各不相同。
tickTime=2000 initLimit=10 syncLimit=5 dataDir=/home/zs/zookeeper/zookeeper1/data dataLogDir=/home/zs/zookeeper/zookeeper1/log clientPort=2181 server.1=IP1:2887:3887 server.2=IP1:2888:3888 server.3=IP1:2889:3889
tickTime=2000 initLimit=10 syncLimit=5 dataDir=/home/zs/zookeeper/zookeeper2/data dataLogDir=/home/zs/zookeeper/zookeeper2/log clientPort=2182 server.1=IP1:2887:3887 server.2=IP1:2888:3888 server.3=IP1:2889:3889
tickTime=2000 initLimit=10 syncLimit=5 dataDir=/home/zs/zookeeper/zookeeper3/data dataLogDir=/home/zs/zookeeper/zookeeper3/log clientPort=2183 server.1=IP1:2887:3887 server.2=IP1:2888:3888 server.3=IP1:2889:3889
(2) 創建myid文件
在每個dataDir所配置的目錄下,創建一個名為myid的文件,在該文件的第一行寫上一個數字,即ServerID,和zoo1.cfg、zoo2.cfg、zoo3.cfg中當前機器的編號對應上。
(3) 啟動服務器
因為只有一個ZooKeeper程序目錄,在啟動不同的實例時,要指定各自的配置文件,啟動命令如下所示
bin/zkServer.sh start conf/zoo1.cfg bin/zkServer.sh start conf/zoo2.cfg bin/zkServer.sh start conf/zoo3.cfg

(4) 驗證服務器
bin/zkServer.sh status conf/zoo1.cfg bin/zkServer.sh status conf/zoo2.cfg bin/zkServer.sh status conf/zoo3.cfg

(5) 關閉服務器
bin/zkServer.sh stop conf/zoo1.cfg bin/zkServer.sh stop conf/zoo2.cfg bin/zkServer.sh stop conf/zoo3.cfg

3. 單機模式
ZooKeeper也支持單機部署,單機模式可以看做一種特殊的集群模式,整體配置流程與集群部署一致,不同的地方在於,zoo.cfg配置文件中,只需要配置一個server地址,而且不需要在dataDir目錄下配置myid文件。
(1) 配置cfg文件
tickTime=2000 initLimit=10 syncLimit=5 dataDir=/home/zs/zookeeper/zookeeper/data dataLogDir=/home/zs/zookeeper/zookeeper/log clientPort=2181 server.1=IP1:2888:3888
(2) 啟動服務器
bin/zkServer.sh start

(3) 驗證服務器
可以使用telnet 加stat命令驗證,也可以使用zkServer.sh status 命令驗證
使用telnet 加stat命令驗證,可以看到單機模式下服務器的Mode為standalone,集群模式下是Leader和Follower。

使用zkServer.sh status 命令驗證

(4) 關閉服務器
bin/zkServer.sh stop

以上就是ZooKeeper的安裝和配置過程。
