1. 程式人生 > >ZooKeeper 安裝部署及hello world

ZooKeeper 安裝部署及hello world

ZooKeeper  安裝部署及hello world


先給一堆學習文件,方便以後檢視
官網文件地址大全:

OverView(概述)
http://zookeeper.apache.org/doc/r3.4.6/zookeeperOver.html

Getting Started(開始入門)
http://zookeeper.apache.org/doc/r3.4.6/zookeeperStarted.html

Tutorial(教程)
http://zookeeper.apache.org/doc/r3.4.6/zookeeperTutorial.html

Java Example(Java示例)
http://zookeeper.apache.org/doc/r3.4.6/javaExample.html

Programmer's Guide(開發人員指南)
http://zookeeper.apache.org/doc/r3.4.6/zookeeperProgrammers.html

Recipes and Solutions(技巧及解決方案)
http://zookeeper.apache.org/doc/r3.4.6/recipes.html

3.4.6 API online(線上API速查)

http://zookeeper.apache.org/doc/r3.4.6/api/index.html

另外推薦園友sunddenly的zookeeper系列
http://www.cnblogs.com/sunddenly/category/620563.html

一、安裝部署


本文在一臺機器上模擬3個 zk server的叢集安裝

1.1 下載解壓

解壓到3個目錄(模擬3臺zk server):

  /home/hadoop/zookeeper-1
  /home/hadoop/zookeeper-2
  /home/hadoop/zookeeper-3
1.2 建立每個目錄下conf/zoo.cfg配置檔案 

/home/hadoop/zookeeper-1/conf/zoo.cfg 內容如下:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/hadoop/tmp/zk1/data
dataLogDir=/home/hadoop/tmp/zk1/log
clientPort=2181
server.1=localhost:2287:3387
server.2=localhost:2288:3388
server.3=localhost:2289:3389

/home/hadoop/zookeeper-2/conf/zoo.cfg 內容如下:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/hadoop/tmp/zk2/data
dataLogDir=/home/hadoop/tmp/zk2/log
clientPort=2182
server.1=localhost:2287:3387
server.2=localhost:2288:3388
server.3=localhost:2289:3389

/home/hadoop/zookeeper-3/conf/zoo.cfg 內容如下:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/hadoop/tmp/zk3/data
dataLogDir=/home/hadoop/tmp/zk3/log
clientPort=2183
server.1=localhost:2287:3387
server.2=localhost:2288:3388
server.3=localhost:2289:3389

注:因為是在一臺機器上模擬叢集,所以埠不能重複,這裡用2181~2183,2287~2289,以及3387~3389相互錯開。另外每個zk的instance,都需要設定獨立的資料儲存目錄、日誌儲存目錄,所以dataDir、dataLogDir這二個節點對應的目錄,需要手動先建立好。

另外還有一個灰常關鍵的設定,在每個zk server配置檔案的dataDir所對應的目錄下,必須建立一個名為myid的檔案,其中的內容必須與zoo.cfg中server.x 中的x相同,即:

/home/hadoop/tmp/zk1/data/myid 中的內容為1,對應server.1中的1
/home/hadoop/tmp/zk2/data/myid 中的內容為2,對應server.2中的2
/home/hadoop/tmp/zk3/data/myid 中的內容為3,對應server.3中的3

生產環境中,分散式叢集部署的步驟與上面基本相同,只不過因為各zk server分佈在不同的機器,上述配置檔案中的localhost換成各伺服器的真實Ip即可。分佈在不同的機器後,不存在埠衝突問題,可以讓每個伺服器的zk均採用相同的埠,這樣管理起來比較方便。

1.3 啟動驗證 

/home/hadoop/zookeeper-1/bin/zkServer.sh start

/home/hadoop/zookeeper-2/bin/zkServer.sh start

/home/hadoop/zookeeper-3/bin/zkServer.sh start
啟用成功後,輸入 jps 看下程序

20351 ZooKeeperMain
20791 QuorumPeerMain
20822 QuorumPeerMain
20865 QuorumPeerMain

應該至少能看到以上幾個程序。

可以啟動客戶端測試下:

bin/zkCli.sh -server localhost:2181
(注:如果是遠端連線,把localhost換成指定的IP即可)

成功後,應該會進到提示符下,類似下面這樣:

[zk: localhost:2181(CONNECTED) 0]  

然後,就可以用一些基礎命令,比如 ls ,create ,delete ,get 來測試了(關於這些命令,大家可以檢視文件),特別提一個很有用的命令rmr 用來遞迴刪除某個節點及其所有子節點

二、java 與 zk的連線示例

2.1 maven專案的pom.xml中先新增以下依賴項
        <!--zk-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
        </dependency>

2.2 最基本的示例程式

package yjmyzz;
 
import java.io.IOException;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
 
public class ZooKeeperHello {
 
    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        ZooKeeper zk = new ZooKeeper("172.28.20.102:2181", 300000, new DemoWatcher());//連線zk server
        String node = "/app1";
        Stat stat = zk.exists(node, false);//檢測/app1是否存在
        if (stat == null) {
            //建立節點
            String createResult = zk.create(node, "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            System.out.println(createResult);
        }
        //獲取節點的值
        byte[] b = zk.getData(node, false, stat);
        System.out.println(new String(b));
        zk.close();
    }
 
    static class DemoWatcher implements Watcher {
        @Override
        public void process(WatchedEvent event) {
            System.out.println("----------->");
            System.out.println("path:" + event.getPath());
            System.out.println("type:" + event.getType());
            System.out.println("stat:" + event.getState());
            System.out.println("<-----------");
        }
    }
}
2.3 與zk叢集的連線

zk的優點之一,就是高可用性,上面的程式碼連線的是單臺zk server,如果這臺server掛了,自然程式碼就會出錯,事實上zk的API考慮到了這一點,把連線程式碼改成下面這樣:

 ZooKeeper zk = new ZooKeeper("172.28.20.102:2181,172.28.20.102:2182,172.28.20.102:2183", 300000, new DemoWatcher());//連線zk server
 
 即:IP1:port1,IP2:port2,IP3:port3...  用這種方式連線叢集就行了,只要有超過半數的zk server還活著,應用一般就沒問題。但是也有一種極罕見的情況,比如這行程式碼執行時,剛初始化完成,正準備連線ip1時,因為網路故障ip1對應的server掛了,仍然會報錯(此時,zk還來不及選出新leader),這個問題詳見:http://segmentfault.com/q/1010000002506725/a-1020000002507402,參考該文的做法,改成:

         ZooKeeper zk = new ZooKeeper("172.28.20.102:2181,172.28.20.102:2182,172.28.20.102:2183", 300000, new DemoWatcher());//連線zk server
         if (!zk.getState().equals(ZooKeeper.States.CONNECTED)) {
             while (true) {
                 if (zk.getState().equals(ZooKeeper.States.CONNECTED)) {
                     break;
                 }
                 try {
                     TimeUnit.SECONDS.sleep(5);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
             }
         }


 但是這樣程式碼未免太冗長,建議用開源的zkClient,官方地址: https://github.com/sgroschupf/zkclient,使用方法很簡單:

        <!--zkclient-->
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>

pom.xml先加這一坨,然後這樣用:

     @Test
     public void testZkClient() {
         ZkClient zkClient = new ZkClient("172.28.20.102:2181,172.28.20.102:2182,172.28.20.102:2183");
         String node = "/app2";
         if (!zkClient.exists(node)) {
             zkClient.createPersistent(node, "hello zk");
         }
         System.out.println(zkClient.readData(node));
     }