要想使用ZooKeeper,首先就要把它部署在服務器上跑起來,就想Apache,Tomcat,FtpServer等服務器一樣。ZooKeeper的部署方式主要有三種,單機模式、偽集群模式、集群模式。其實單機和偽集群都是集群模式的特殊情況。
一、 單機模式
ZooKeeper的單機模式通常是用來快速測試客戶端應用程序的,在實際過程中不可能是單機模式。單機模式的配置也比較簡單。
1.編寫配置文件zoo.cfg
zookeeper-3.3.3/conf文件夾下面就是要編寫配置文件的位置了。在文件夾下面新建一個文件zoo.cfg。ZooKeeper的運行默認是讀取zoo.cfg文件里面的內容的。以下是一個最簡單的配置文件的樣例:
tickTime=2000
dataDir=/var/zookeeper
clientPort=2181
在這個文件中,我們需要指定 dataDir 的值,它指向了一個目錄,這個目錄在開始的時候需要為空。下面是每個參數的含義:
tickTime :基本事件單元,以毫秒為單位。這個時間是作為 Zookeeper 服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是每個 tickTime 時間就會發送一個心跳。
dataDir :存儲內存中數據庫快照的位置,顧名思義就是 Zookeeper 保存數據的目錄,默認情況下,Zookeeper 將寫數據的日志文件也保存在這個目錄里。
clientPort :這個端口就是客戶端連接 Zookeeper 服務器的端口,Zookeeper 會監聽這個端口,接受客戶端的訪問請求。
使用單機模式時用戶需要注意:這種配置方式下沒有 ZooKeeper 副本,所以如果 ZooKeeper 服務器出現故障, ZooKeeper 服務將會停止。
2.執行運行腳本
在zookeeper-3.3.3/bin文件夾下面運行zkServer.sh即可,運行完畢之后則ZooKeeper服務變啟動起來。
./zkServer.sh start
腳本默認調用zoo.cfg里面的配置,因此程序正常啟動。
二、ZooKeeper的集群模式部署
ZooKeeper的集群模式下,多個Zookeeper服務器在工作前會選舉出一個Leader,在接下來的工作中這個被選舉出來的Leader死了,而剩下的Zookeeper服務器會知道這個Leader死掉了,在活着的Zookeeper集群中會繼續選出一個Leader,選舉出Leader的目的是為了可以在分布式的環境中保證數據的一致性。
l.確認集群服務器的數量
由於ZooKeeper集群中,會有一個Leader負責管理和協調其他集群服務器,因此服務器的數量通常都是單數,例如3,5,7...等,這樣2n+1的數量的服務器就可以允許最多n台服務器的失效。
2.編寫配置文件
zookeeper-3.3.3/conf文件夾下面(可以把默認的zoosample.cfg復制一份到zoo.cfg),配置文件zoo.cfg需要在每台服務器中都要編寫,以下是一個配置文件的樣本:
# Filename zoo.cfg
tickTime=2000
dataDir=/home/zookeeper/data
clientPort=2181
initLimit=5
syncLimit=2
server.1=202.115.36.251:2888:3888
server.2=202.115.36.241:2888:3888
server.3=202.115.36.242:2888:3888
initLimit:這個配置項是用來配置 Zookeeper 接受客戶端(這里所說的客戶端不是用戶連接 Zookeeper 服務器的客戶端,而是 Zookeeper 服務器集群中連接到 Leader 的 Follower 服務器)初始化連接時最長能忍受多少個心跳時間間隔數。當已經超過 10 個心跳的時間(也就是 tickTime)長度后 Zookeeper 服務器還沒有收到客戶端的返回信息,那么表明這個客戶端連接失敗。總的時間長度就是 5*2000=10 秒。
syncLimit:這個配置項標識 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 2*2000=4 秒
server.A=B:C:D:其中 A 是一個數字,表示這個是第幾號服務器;B 是這個服務器的 ip 地址;C 表示的是這個服務器與集群中的 Leader 服務器交換信息的端口;D 表示的是萬一集群中的 Leader 服務器掛了,需要一個端口來重新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通信的端口。如果是偽集群的配置方式,由於 B 都是一樣,所以不同的 Zookeeper 實例通信端口號不能一樣,所以要給它們分配不同的端口號。
3.創建myid文件
除了修改 zoo.cfg 配置文件,集群模式下還要配置一個文件 myid,這個文件在 dataDir 目錄下,這個文件里面就只有一個數據就是 A 的值,Zookeeper 啟動時會讀取這個文件,拿到里面的數據與 zoo.cfg 里面的配置信息比較從而判斷到底是那個 server。這個myid的值要和配置文件中的server.x=ip:port:port中的x一致。
在251的dataDir執行:echo "1">myid
4.執行運行腳本
和單機模式下的運行方式基本相同,值得注意的地方就是要分別在不同服務器上執行一次,例如分別在251,241,242上運行:
./zkServer.sh start
這樣才能使得整個集群啟動起來。
5. 通過ZooKeeper命令行工具訪問ZooKeeper
ZooKeeper命令行工具類似於Linux的shell環境,不過功能肯定不及shell啦,但是使用它我們可以簡單的對ZooKeeper進行訪問,數據創建,數據修改等操作。
當啟動 ZooKeeper 服務成功之后,輸入下述命令,連接到 ZooKeeper 服務:
zkCli.sh –server 202.115.36.251:2181
連接成功后,系統會輸出 ZooKeeper 的相關環境以及配置信息,並在屏幕輸出“ Welcome to ZooKeeper ”等信息。
命令行工具的一些簡單操作如下:
1 )使用 ls 命令來查看當前 ZooKeeper 中所包含的內容:
[zk: 202.115.36.251:2181(CONNECTED) 1] ls /
2 )創建一個新的 znode ,使用 create /zk myData 。這個命令創建了一個新的 znode 節點“ zk ”以及與它關聯的字符串:
[zk: 202.115.36.251:2181(CONNECTED) 2] create /zk "myData"
3 )我們運行 get 命令來確認 znode 是否包含我們所創建的字符串:
[zk: 202.115.36.251:2181(CONNECTED) 3] get /zk
4 )下面我們通過 set 命令來對 zk 所關聯的字符串進行設置:
[zk: 202.115.36.251:2181(CONNECTED) 4] set /zk "zsl"
5 )下面我們將剛才創建的 znode 刪除:
[zk: 202.115.36.251:2181(CONNECTED) 5] delete /zk
6. 使用Java API來訪問ZooKeeper
API訪問ZooKeeper才是客戶端主要的使用手段,通過在客戶端編寫豐富多彩的程序,來達到對ZooKeeper的利用。這里給出一個簡單的例子:
可以通過客戶端腳本,連接到ZooKeeper集群上。對於客戶端來說,ZooKeeper是一個整體(ensemble),連接到ZooKeeper集群實際上感覺在獨享整個集群的服務,所以,你可以在任何一個結點上建立到服務集群的連接
import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; public class T { public static void main(String[] args) throws Exception { // 創建一個與服務器的連接 ZooKeeper zk = new ZooKeeper("220.181.8.230:2181,220.181.8.149:2181,220.181.8.199:2181", 1000 * 60, new Watcher() { // 監控所有被觸發的事件 public void process(WatchedEvent event) { System.out.println("已經觸發了" + event.getType() + "事件!"); } }); // 創建一個目錄節點 zk.create("/testRootPath", "testRootData".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); // 創建一個子目錄節點 zk.create("/testRootPath/testChildPathOne", "testChildDataOne".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out .println(new String(zk.getData("/testRootPath", false, null))); // 取出子目錄節點列表 System.out.println(zk.getChildren("/testRootPath", true)); // 修改子目錄節點數據 zk.setData("/testRootPath/testChildPathOne", "modifyChildDataOne".getBytes(), -1); System.out.println("目錄節點狀態:[" + zk.exists("/testRootPath", true) + "]"); // 創建另外一個子目錄節點 zk.create("/testRootPath/testChildPathTwo", "testChildDataTwo".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println(new String(zk.getData( "/testRootPath/testChildPathTwo", true, null))); // 刪除子目錄節點 zk.delete("/testRootPath/testChildPathTwo", -1); zk.delete("/testRootPath/testChildPathOne", -1); // 刪除父目錄節點 zk.delete("/testRootPath", -1); // 關閉連接 zk.close(); } }
7. 查看zookeeper的各節點狀態
可以通過ZooKeeper的腳本來查看啟動狀態,包括集群中各個結點的角色(或是Leader,或是Follower),如下所示,是在ZooKeeper集群中的每個結點上查詢的結果:zkServer.sh status
hadoop@slave-01:~/installation/zookeeper-3.3.4$ bin/zkServer.sh status
- JMX enabled by default
- Using config: /home/hadoop/installation/zookeeper-3.3.4/bin/../conf/zoo.cfg
- Mode: follower
- hadoop@slave-02:~/installation/zookeeper-3.3.4$ bin/zkServer.sh status
- JMX enabled by default
- Using config: /home/hadoop/installation/zookeeper-3.3.4/bin/../conf/zoo.cfg
- Mode: leader
- hadoop@slave-03:~/installation/zookeeper-3.3.4$ bin/zkServer.sh status
- JMX enabled by default
- Using config: /home/hadoop/installation/zookeeper-3.3.4/bin/../conf/zoo.cfg
- Mode: follower
8、清除zk狀態
當在zk上已經做了很多事情,配置已經比較雜亂,現在想重新初始化一下,也就是把所有狀態刪除,步驟是:
8.1 關閉所有zk節點,用zkServer.sh status查看是否關閉
8.2 刪除zoo.cfg定義的數據文件夾下的所有文件,除了myid文件外
8.3 啟動zk節點
現在配置就重置了
9、常見問題:
9.1 在用zkCli.sh啟動客戶端時,Will not attempt to authenticate using SASL (無法定位登錄配置)
這是由於沒有啟用用戶驗證導致的,不影響使用,但影響安全性。SASL 即:Simple Authentication and Security Layer
源碼來源: minglisoft.cn/technology