Docker安裝&java-Zookeeper進行操作
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的連線資訊
https://img-blog.csdn.net/20180702163121669?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI2NjQxNzgx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70
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幾個組成部分
Client: 是ZooKeeper客戶端的一個替代品, 提供了一些底層處理和相關的工具方法
Framework: 用來簡化ZooKeeper高階功能的使用, 並增加了一些新的功能, 比如管理到ZooKeeper叢集的連線, 重試處理
Recipes: 實現了通用ZooKeeper的recipe, 該元件建立在Framework的基礎之上
Utilities:各種ZooKeeper的工具類
Errors: 異常處理, 連線, 恢復等
Extensions: recipe擴充套件
Curator主要解決了三類問題
封裝ZooKeeper client與ZooKeeper server之間的連線處理
提供了一套Fluent風格的操作API
提供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使用的複雜性
重試機制:提供可插拔的重試機制, 它將給捕獲所有可恢復的異常配置一個重試策略,並且內部也提供了幾種標準的重試策略(比如指數補償)
連線狀態監控: Curator初始化之後會一直的對zk連線進行監聽, 一旦發現連線狀態發生變化, 將作出相應的處理
zk客戶端例項管理:Curator對zk客戶端到server叢集連線進行管理.並在需要的情況, 重建zk例項,保證與zk叢集的可靠連線
各種使用場景支援:Curator實現zk支援的大部分使用場景支援(甚至包括zk自身不支援的場景),這些實現都遵循了zk的最佳實踐,並考慮了各種極端情況
Curator聲稱的一些亮點
日誌工具
內部採用SLF4J 來輸出日誌 採用驅動器(driver)機制, 允許擴充套件和定製日誌和跟蹤處理,
提供了一個TracerDriver介面, 通過實現addTrace()和addCount()介面來整合使用者自己的跟蹤框架
和Curator相比, 另一個ZooKeeper客戶端——zkClient的不足之處
文件幾乎沒有異常處理弱爆了(簡單的丟擲RuntimeException) 重試處理太難用了 沒有提供各種使用場景的實現
對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"); } }
節點型別說明:
節點型別有4種:“PERSISTENT、PERSISTENT_SEQUENTIAL、EPHEMERAL、EPHEMERAL_SEQUENTIAL”其中“EPHEMERAL、EPHEMERAL_SEQUENTIAL”兩種是客戶端斷開連線(Session無效時)節點會被自動刪除;“PERSISTENT_SEQUENTIAL、EPHEMERAL_SEQUENTIAL”兩種是節點名字尾是一個自動增長序號。
節點訪問許可權說明:
節點訪問許可權由List確定,但是有幾個便捷的靜態屬性可以選擇:
- Ids.CREATOR_ALL_ACL:只有建立節點的客戶端才有所有許可權\
- Ids.OPEN_ACL_UNSAFE:這是一個完全開放的許可權,所有客戶端都有許可權
- Ids.READ_ACL_UNSAFE:所有客戶端只有讀取的
zkclient :
public class Zkclient { public static void main(String[] args) throws Exception{ ZkClient zkClient = new ZkClient("192.168.0.183:2181");//建立連線 zkClient.create("/root","mydata", CreateMode.PERSISTENT);//建立目錄並寫入資料 String data=zkClient.readData("/root"); System.out.println(data); //zkClient.delete("/root");//刪除目錄 //zkClient.deleteRecursive("/root");//遞迴刪除節目錄 } }
特別感謝資料來源:https://www.cnblogs.com/LiZhiW/p/4923693.html