1. 程式人生 > 實用技巧 >Docker安裝Zookeeper並進行操作

Docker安裝Zookeeper並進行操作

轉載:https://blog.csdn.net/qq_26641781/article/details/80886831

Docker安裝Zookeeper

  • 下載Zookeeper映象
docker pull zookeeper
  • 啟動容器並新增對映
docker run --privileged=true -d --name zookeeper --publish 2181:2181  -d zookeeper:latest
  • 檢視容器是否啟動
docker ps

  

idea提供了一個Zookeeper外掛,以供連線Zookeeper服務中心和檢視內容

  • 開啟idea –》 Settings -》Plugins,搜尋Zoo進行下載安裝

  • 配置Zookeeper的連線資訊

ZooKeeper常用客戶端

zookeeper的常用客戶端有3種,分別是:zookeeper原生的、Apache Curator、開源的zkclient,下面分別對介紹它們:
zookeeper自帶的客戶端是官方提供的,比較底層、使用起來寫程式碼麻煩、不夠直接。
Apache Curator是Apache的開源專案,封裝了zookeeper自帶的客戶端,使用相對簡便,易於使用。
zkclient是另一個開源的ZooKeeper客戶端。

三個客戶端的Maven座標

<dependencies>
        <!-- 原生zookeeper -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
        </dependency>

        <!--Apache Curator-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.9.0</version>
        </dependency>

        <!-- zkclient -->
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.9</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

    </dependencies>

三種ZooKeeper客戶端比較
由於Apache Curator是其中比較完美的ZooKeeper客戶端,所以主要介紹Curator的特性來進行比較!

Curator幾個組成部分

  1. Client: 是ZooKeeper客戶端的一個替代品, 提供了一些底層處理和相關的工具方法
  2. Framework: 用來簡化ZooKeeper高階功能的使用, 並增加了一些新的功能, 比如管理到ZooKeeper叢集的連線, 重試處理
  3. Recipes: 實現了通用ZooKeeper的recipe, 該元件建立在Framework的基礎之上
  4. Utilities:各種ZooKeeper的工具類
  5. Errors: 異常處理, 連線, 恢復等
  6. Extensions: recipe擴充套件

Curator主要解決了三類問題

  1. 封裝ZooKeeper client與ZooKeeper server之間的連線處理
  2. 提供了一套Fluent風格的操作API
  3. 提供ZooKeeper各種應用場景(recipe, 比如共享鎖服務, 叢集領導選舉機制)的抽象封裝

Curator列舉的ZooKeeper使用過程中的幾個問題

  • 初始化連線的問題:
    在client與server之間握手建立連線的過程中,如果握手失敗,執行所有的同步方法(比如create,getData等)將丟擲異常
  • 自動恢復(failover)的問題: 當client與一臺server的連線丟失,並試圖去連線另外一臺server時,
    client將回到初始連線模式
  • session過期的問題: 在極端情況下,出現ZooKeeper
    session過期,客戶端需要自己去監聽該狀態並重新建立ZooKeeper例項
  • 對可恢復異常的處理:當在server端建立一個有序ZNode,而在將節點名返回給客戶端時崩潰,此時client端丟擲可恢復的異常,使用者需要自己捕獲這些異常並進行重試
  • 使用場景的問題:Zookeeper提供了一些標準的使用場景支援,但是ZooKeeper對這些功能的使用說明文件很少,而且很容易用錯.在一些極端場景下如何處理,zk並沒有給出詳細的文件說明.比如共享鎖服務,當伺服器端建立臨時順序節點成功,但是在客戶端接收到節點名之前掛掉了,如果不能很好的處理這種情況,將導致死鎖

Curator主要從以下幾個方面降低了zk使用的複雜性

  1. 重試機制:提供可插拔的重試機制, 它將給捕獲所有可恢復的異常配置一個重試策略,並且內部也提供了幾種標準的重試策略(比如指數補償)
  2. 連線狀態監控: Curator初始化之後會一直的對zk連線進行監聽, 一旦發現連線狀態發生變化, 將作出相應的處理
  3. zk客戶端例項管理:Curator對zk客戶端到server叢集連線進行管理.並在需要的情況, 重建zk例項,保證與zk叢集的可靠連線
  4. 各種使用場景支援:Curator實現zk支援的大部分使用場景支援(甚至包括zk自身不支援的場景),這些實現都遵循了zk的最佳實踐,並考慮了各種極端情況

Curator聲稱的一些亮點

  1. 日誌工具
    內部採用SLF4J 來輸出日誌 採用驅動器(driver)機制, 允許擴充套件和定製日誌和跟蹤處理,
    提供了一個TracerDriver介面, 通過實現addTrace()和addCount()介面來整合使用者自己的跟蹤框架
  2. 和Curator相比, 另一個ZooKeeper客戶端——zkClient的不足之處
    文件幾乎沒有異常處理弱爆了(簡單的丟擲RuntimeException) 重試處理太難用了 沒有提供各種使用場景的實現
  3. 對ZooKeeper自帶客戶端(ZooKeeper類)的”抱怨” 只是一個底層實現 要用需要自己寫大量的程式碼 很容易誤用
    需要自己處理連線丟失, 重試等

測試程式碼:

public class CuratorTest {
    public static void main(String[] args) throws Exception{
        CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.0.183:2181", new RetryNTimes(10, 5000));
        client.start();// 連線
        // 獲取子節點,順便監控子節點
        List<String> children = client.getChildren().usingWatcher(new CuratorWatcher() {
            public void process(WatchedEvent event) throws Exception
            {
                System.out.println("監控: " + event);
            }
        }).forPath("/");
        System.out.println(children);
        // 建立節點
        String result = client.create().withMode(CreateMode.PERSISTENT).withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE).forPath("/test", "Data".getBytes());
        System.out.println(result);
        // 設定節點資料
        client.setData().forPath("/test", "111".getBytes());
        client.setData().forPath("/test", "222".getBytes());
        // 刪除節點
        //System.out.println(client.checkExists().forPath("/test"));
        /*client.delete().withVersion(-1).forPath("/test");
        System.out.println(client.checkExists().forPath("/test"));*/
        client.close();
        System.out.println("OK!");
    }
}

ZooKeeper自帶客戶端(原生zookeeper)
ZooKeeper自帶客戶端的主要類是ZooKeeper類,ZooKeeper類物件除了需要ZooKeeper服務端連線字串(IP地址:埠),還必須提供一個Watcher物件。Watcher是一個介面,當伺服器節點花發生變化就會以事件的形式通知Watcher物件。所以Watcher常用來監聽節點,當節點發生變化時客戶端就會知道。\

ZooKeeper類還有對節點進行增刪改的操作方法,主要方法如下:

    • create:用於建立節點,可以指定節點路徑、節點資料、節點的訪問許可權、節點型別
    • delete:刪除節點,每個節點都有一個版本,刪除時可指定刪除的版本,類似樂觀鎖。設定-1,則就直接刪除節點。
    • exists:節點存不存在,若存在返回節點Stat資訊,否則返回null
    • getChildren:獲取子節點
    • getData/setData:獲取節點資料
    • getACL/setACL:獲取節點訪問許可權列表,每個節點都可以設定訪問許可權,指定只有特定的客戶端才能訪問和操作節點。
      • public class ZookpeerTest {
            public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
                ZooKeeper zk = new ZooKeeper("192.168.0.183:2181", 3000, new Watcher() {
                    public void process(WatchedEvent watchedEvent) {
                        System.out.println(watchedEvent.toString());
                    }
                });
                System.out.println("OK!");
                // 建立一個目錄節點
                /**
                 * CreateMode:
                 *       PERSISTENT (持續的,相對於EPHEMERAL,不會隨著client的斷開而消失)
                 *       PERSISTENT_SEQUENTIAL(持久的且帶順序的)
                 *       EPHEMERAL (短暫的,生命週期依賴於client session)
                 *       EPHEMERAL_SEQUENTIAL  (短暫的,帶順序的)
                 */
                zk.create("/country", "China".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                // 建立一個子目錄節點
                zk.create("/country/city", "China/Hangzhou".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                System.out.println(new String(zk.getData("/country", false, null)));
                // 取出子目錄節點列表
                System.out.println(zk.getChildren("/country", true));
                // 建立另外一個子目錄節點
                zk.create("/country/view", "China/WestLake".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                System.out.println(zk.getChildren("/country", true));
                // 修改子目錄節點資料
                zk.setData("/country/city", "China/Shanghai".getBytes(), -1);
                byte[] datas = zk.getData("/country/city", true, null);
                String str = new String(datas, "utf-8");
                System.out.println(str);
                // 刪除整個子目錄 -1代表version版本號,-1是刪除所有版本
        //        zk.delete("/path01/path01", -1);
        //        zk.delete("/path01/path02", -1);
        //        zk.delete("/path01", -1);
        //        System.out.println(str);
                Thread.sleep(15000);
                zk.close();
                System.out.println("OK");
            }
        }