Zookeeper(八)-zookeeper客戶端Curator
zookeeper的原生api相對來說比較繁瑣,比如:對節點新增監聽事件,當監聽觸發後,我們需要再次手動新增監聽,否則監聽只生效一次;再比如,斷線重連也需要我們手動程式碼來判斷處理等等。對於curator的介紹,從網上百度了一段:Curator是Netflix開源的一套zookeeper客戶端框架,用它來操作zookeeper更加方便,按Curator官方所比喻的,guava to JAVA,curator to zookeeper,Curator採用了fluent風格的程式碼,非常簡潔。
和Curator相比, 另一個ZooKeeper客戶端——zkClient(https://github.com/sgroschupf/zkclient
文件幾乎沒有
異常處理弱爆了(簡單的丟擲RuntimeException)
重試處理太難用了
沒有提供各種使用場景的實現
對ZooKeeper自帶客戶端(ZooKeeper類)的"抱怨":
只是一個底層實現
要用需要自己寫大量的程式碼
很容易誤用
需要自己處理連線丟失, 重試等
----------------------------------------------------------------------------------------------------------------------------------
Curator包含6部分,均可提供單獨jar包,每個包簡單介紹如下:
client:zk-client的替代品,提供一些底層處理跟工具類;
framework:高階封裝,大大簡化了zk的客戶端程式設計,包含對zk的連線管理,重試機制等;
repices:提供了一些常用的操作,比如持續監聽,鎖,選舉等;
utilities:各種工具類;
errors:curator對異常跟錯誤的處理;
extendsion:擴充套件包;
maven依賴如下
Xml程式碼- <dependency>
- <groupId>org.apache.curator</groupId>
- <artifactId>curator-recipes
- <version>2.5.0</version>
- </dependency>
按照官方給出的文件和包結構,可以輕鬆的看出Curator功能分兩大類,一是對zookeeper的一些基本命令的封裝,比如增刪改查。是他的framework模組,一個是他的高階特性,即recipes模組。
一、framework模組
Curator提供了一套Fluent風格的操作API。這在很多指令碼類語言裡比較流行。
比如他建立client的程式碼是這樣
Java程式碼- CuratorFramework client = builder.connectString("192.168.11.56:2180")
- .sessionTimeoutMs(30000)
- .connectionTimeoutMs(30000)
- .canBeReadOnly(false)
- .retryPolicy(new ExponentialBackoffRetry(1000, Integer.MAX_VALUE))
- .namespace(namespace)
- .defaultData(null)
- .build();
- client.start();
一路點到底,這就是所謂的Fluent風格。
我們再看增刪改查的
Java程式碼- publicclass CrudExamples {
- privatestatic CuratorFramework client = ClientFactory.newClient();
- privatestaticfinal String PATH = "/crud";
- publicstaticvoid main(String[] args) {
- try {
- client.start();
- client.create().forPath(PATH, "I love messi".getBytes());
- byte[] bs = client.getData().forPath(PATH);
- System.out.println("新建的節點,data為:" + new String(bs));
- client.setData().forPath(PATH, "I love football".getBytes());
- // 由於是在background模式下獲取的data,此時的bs可能為null
- byte[] bs2 = client.getData().watched().inBackground().forPath(PATH);
- System.out.println("修改後的data為" + new String(bs2 != null ? bs2 : newbyte[0]));
- client.delete().forPath(PATH);
- Stat stat = client.checkExists().forPath(PATH);
- // Stat就是對zonde所有屬性的一個對映, stat=null表示節點不存在!
- System.out.println(stat);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- CloseableUtils.closeQuietly(client);
- }
- }
- }
常用介面有
create()增
delete(): 刪
checkExists(): 判斷是否存在
setData(): 改
getData(): 查
所有這些方法都以forpath()結尾,輔以watch(監聽),withMode(指定模式),和inBackground(後臺執行)等方法來使用。
(補充) 1、建立連線
建立連線需要指定zk地址以及重試策略等,先上程式碼再解釋:
1234567891011121314 | RetryPolicy retry = new ExponentialBackoffRetry( 1000 , 5 ); //重試5次,每次間隔時間指數增長(有具體增長公式) RetryPolicy retry1 = new RetryNTimes( 5 , 5000 ); //重試5次,每次間隔5秒 RetryPolicy retry2 = new RetryUntilElapsed( 60000 * 2 , 5000 ); //重試2分鐘,每次間隔5秒<br> //普通建立 CuratorFramework client = CuratorFrameworkFactory.newClient( "localhost:2181" , 5000 , 5000 , retry); //fluent風格建立 CuratorFramework client1 = CuratorFrameworkFactory.builder() .connectString( "localhost:2181" ) .connectionTimeoutMs( 5000 ) //連線超時時間 .sessionTimeoutMs( 3000 ) //會話超時時間 .retryPolicy(retry) .build(); //建立連線 client.start(); |
如註釋,建立客戶端連線我們通常需要指定重試策略,curator提供了3種重試機制,分別如上;對於fluent風格,就是每個操作都返回了一個物件,我們可以一直通過[.方法名]的方式書寫程式碼;client建立了之後,需要呼叫start方法才能真正去建立連線。會話超時時間是指當連線發生故障時,由於zk的心跳機制檢測,服務端認為會話超時的時間,會清除session;
2、建立、刪除、更新節點
連線建立之後,我們可以在伺服器上進行建立節點的操作,程式碼如下:
1234567891011121314151617181920 | //建立節點 String path = client.create() .creatingParentsIfNeeded() //對節點路徑上沒有的節點進行建立 .withMode(CreateMode.EPHEMERAL) //臨時節點 .forPath( "/curator/test" , "123" .getBytes()); //節點路徑,節點的值 //刪除節點 client.delete() .guaranteed() //刪除失敗,則客戶端持續刪除,直到節點刪除為止 .deletingChildrenIfNeeded() //刪除相關子節點 .withVersion(- 1 ) //無視版本,直接刪除 .forPath( "/curator/mytest" ); //更新節點資訊 Stat stat2 = new Stat(); byte [] theValue2 = client.getData().storingStatIn(stat).forPath( "/curator/test" ); client.setData() .withVersion(stat2.getVersion()) //版本校驗,與當前版本不一致則更新失敗,-1則無視版本資訊進行更新 .forPath( "/curator/test" , "456" .getBytes()); //判斷節點是否存在(存在返回節點資訊,不存在則返回null) Stat s = client.checkExists().forPath( "/curator/test" ); |
持久節點是persistent,我們建立的節點可能有好幾層,如果伺服器不存在父節點則會報錯並建立失敗,createingParentsIfNodeed()的作用是在父節點不存在的時候進行建立。刪除操作可能由於網路抖動等情況導致刪除失敗,由於節點資料操作一般對業務影響較大,故多數都會帶持續刪除的動作來確保正確刪除;節點更新刪除等操作若考慮版本校驗,則採用程式碼所示方式,在獲取節點資料的時候對節點狀態進行賦值,然後通過節點狀態可以獲得版本資訊。判斷節點是否存在,一般通過節點資訊判斷,若不存在,則節點資訊為null。
3、獲取位元組點列表
只有一行程式碼,返回string型別的list
12 | //獲取子節點列表 List<String> paths = client.getChildren().forPath( "/curator" ); |
4、非同步操作
非同步操作不會阻塞程式碼執行,對於操作完成後的業務處理,需要設定回撥函式來完成。以判斷節點是否存在為例:
123456789101112131415 | ExecutorService es = Executors.newFixedThreadPool( 5 ); //非同步操作執行緒池, //非同步判斷操作 Stat s1 = client.checkExists().inBackground().forPath( "/curator/test" ); //無回撥 client.checkExists().inBackground( new BackgroundCallback() { //有回撥 @Override public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception { CuratorEventType c = curatorEvent.getType(); //事件型別,可在CuratorEventType看到具體種類 int r = curatorEvent.getResultCode(); //0,執行成功,其它,執行失敗 Object o = curatorEvent.getContext(); //事件上下文,一般是由呼叫方法傳入,供回撥函式使用的引數 String p = curatorEvent.getPath(); //節點路徑 List<String> li = curatorEvent.getChildren(); //子節點列表 byte [] datas = curatorEvent.getData(); //節點資料 //一些其它操作 } },es).forPath( "/curator/test" ); |
非同步操作實際是在後臺另起一個執行緒來完成該操作,若執行緒較多勢必會影響伺服器效能,所以要用執行緒池來儘量降低對伺服器的消耗。需要考慮執行緒池的關閉操作,較繁瑣,不作贅述。
5、節點、子節點監聽
節點監聽需要用repices包中的NodeCache來完成,程式碼如下:
12345678910 | //節點監聽 final NodeCache cache = new NodeCache(client, "/curator/test" ); cache.start(); cache.getListenable().addListener( new NodeCacheListener() { //監聽物件 @Override public void nodeChanged() throws Exception { //重寫監聽方法 byte [] ret = cache.getCurrentData().getData(); System.out.println( "當前節點內容是:" + new String(ret)); } }); |
子節點的監聽需要用PathChildrenCache來完成,跟節點本身不一樣,程式碼如下:
1234567891011121314151617181920 | //子節點監聽 final PathChildrenCache pccache = new PathChildrenCache(client, "/curator" , true ); //true指當子節點變化時,獲取子節點內容 pccache.start(); pccache.getListenable().addListener( new PathChildrenCacheListener() { @Override public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception { //重寫監聽方法 switch (pathChildrenCacheEvent.getType()){ //子節點的事件型別 case CHILD_ADDED: System.out.println(pathChildrenCacheEvent.getData()); //通過pathChildrenCacheEvent,可以獲取到節點相關的資料 break ; case CHILD_REMOVED: System.out.println(pathChildrenCacheEvent.getData().getPath()); break ; case CHILD_UPDATED: break ; default : break ; } } }); |
6、許可權控制部分,略。
此外,Curator還支援事務,一組crud操作同生同滅。程式碼如下
Java程式碼- /**
- * 事務操作
- *
- * @author shencl
- */
- publicclass TransactionExamples {
- privatestatic CuratorFramework client = ClientFactory.newClient();
- publicstaticvoid main(String[] args) {
- try {
- client.start();
- // 開啟事務
- CuratorTransaction transaction = client.inTransaction();
- Collection<CuratorTransactionResult> results = transaction.create()
- .forPath("/a/path", "some data".getBytes()).and().setData()
- .forPath("/another/path", "other data".getBytes()).and().delete().forPath("/yet/another/path")
- .and().commit();
- for (CuratorTransactionResult result : results) {
- System.out.println(result.getForPath() + " - " + result.getType());
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 釋放客戶端連線
- CloseableUtils.closeQuietly(client);
- }
- }
- }
這段的程式碼的執行結果,由於最後一步delete的節點不存在,所以整個事務commit失敗。失敗的原因會放在Collection<CuratorTransactionResult>中,非常友好。
好了framework部分的內容就這麼多,是不是特別簡單呢。下面就來看看recipes包的內容吧。。
Recipes部分提供的功能官網列的很詳細,點選這裡。注意文章第一段:Curator宣稱,Recipes模組實現了除二階段提交之外的所有zookeeper特性。
二、Recipes模組
主要有
Elections(選舉),Locks(鎖),Barriers(關卡),Atomic(原子量),Caches,Queues等
1、 Elections
選舉主要依賴於LeaderSelector和LeaderLatch2個類。前者是所有存活的客戶端不間斷的輪流做Leader,大同社會。後者是一旦選舉出Leader,除非有客戶端掛掉重新觸發選舉,否則不會交出領導權。某黨?
這兩者在實現上是可以切換的,直接上程式碼,怎麼切換註釋裡有。由於篇幅所限,這裡僅貼出基於LeaderSelector的選舉,更多程式碼見附件
Java程式碼- /**
- * 本類基於leaderSelector實現,所有存活的client會公平的輪流做leader
- * 如果不想頻繁的變化Leader,需要在takeLeadership方法裡阻塞leader的變更! 或者使用 {@link}
- * LeaderLatchClient
- */
- publicclass LeaderSelectorClient extends LeaderSelectorListenerAdapter implements Closeable {
- privatefinal String name;
- privatefinal LeaderSelector leaderSelector;
- privatefinal String PATH = "/leaderselector";
- public LeaderSelectorClient(CuratorFramework client, String name) {
- this.name = name;
- leaderSelector = new LeaderSelector(client, PATH, this);
- leaderSelector.autoRequeue();
- }
- publicvoid start() throws IOException {
- leaderSelector.start();
- }
- @Override
- publicvoid close() throws IOException {
- leaderSelector.close();
- }
- /**
- * client成為leader後,會呼叫此方法
- */
- @Override
- publicvoid takeLeadership(CuratorFramework client) throws Exception {
- int waitSeconds = (int) (5 * Math.random()) + 1;
- System.out.println(name + "是當前的leader");
- try {
- Thread.sleep(TimeUnit.SECONDS.toMillis(waitSeconds));
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- } finally {
- System.out.println(name + " 讓出領導權\n");
- }
- }
- /**
- * leader選舉
- *
- * @author shencl
- */
- publicclass LeaderSelectorExample {
- publicstaticvoid main(String[] args) {
- List<CuratorFramework> clients = Lists.newArrayList();
- List<LeaderSelectorClient> examples = Lists.newArrayList();
- try {
- for (int i = 0; i < 10; i++) {
- CuratorFramework client = ClientFactory.newClient();
- LeaderSelectorClient example = new LeaderSelectorClient(client, "Client #" + i);
- clients.add(client);
- examples.add(example);
- client.start();
- example.start();
- }
- System.out.println("----------先觀察一會選舉的結果-----------");
- Thread.sleep(10000);
- System.out.println("----------關閉前5個客戶端,再觀察選舉的結果-----------");
- for (int i = 0; i < 5; i++) {
- clients.get(i).close();
- }
- // 這裡有個小技巧,讓main程式一直監聽控制檯輸入,非同步的程式碼就可以一直在執行。不同於while(ture)的是,按回車或esc可退出
- new BufferedReader(new InputStreamReader(System.in)).readLine();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- for (LeaderSelectorClient exampleClient : examples) {
- CloseableUtils.closeQuietly(exampleClient);
- }
- for (CuratorFramework client : clients) {
- CloseableUtils.closeQuietly(client);
- }
- }
- }
- }
2、locks
curator lock相關的實現在recipes.locks包裡。頂級介面都是InterProcessLock。我們直接看最有代表性的InterProcessReadWriteLock 程序內部讀寫鎖(可重入讀寫鎖)。什麼叫可重入,什麼叫讀寫鎖。不清楚的先查好資料吧。總之讀寫鎖一定是成對出現的。 簡易傳送門
我們先定義兩個任務,可並行的執行的,和互斥執行的。
Java程式碼- /**
- * 並行任務
- *
- * @author shencl
- */
- publicclass ParallelJob implements Runnable {
- privatefinal String name;
- privatefinal InterProcessLock lock;
- // 鎖等待時間
- privatefinalint wait_time = 5;
- ParallelJob(String name, InterProcessLock lock) {
- this.name = name;
- this.lock = lock;
- }
- @Override
- publicvoid run() {
- try {
- doWork();
- } catch (Exception e) {
- // ingore;
- }
- }
- publicvoid doWork() throws Exception {
- try {
- if (!lock.acquire(wait_time, TimeUnit.SECONDS)) {
- System.err.println(name + "等待" + wait_time + "秒,仍未能獲取到lock,準備放棄。");
- }
- // 模擬job執行時間0-4000毫秒
- int exeTime = new Random().nextInt(4000);
- System.out.println(name + "開始執行,預計執行時間= " + exeTime + "毫秒----------");
- Thread.sleep(exeTime);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- lock.release();
- }
- }
- }
- /**
- * 互斥任務
- *
- * @author shencl
- */
- publicclass MutexJob implements Runnable {
- privatefinal String name;
- privatefinal InterProcessLock lock;
- // 鎖等待時間
- privatefinalint wait_time = 10;
- MutexJob(String name, InterProcessLock lock) {
- this.name = name;
- this.lock = lock;
- }
- @Override
- publicvoid run() {
- try {
- doWork();
- } catch (Exception e) {
- // ingore;
- }
- }
- publicvoid doWork() throws Exception {
- try {
- if (!lock.acquire(wait_time, TimeUnit.SECONDS)) {
- System.err.println(name + "等待" + wait_time + "秒,仍未能獲取到lock,準備放棄。");
- }
- // 模擬job執行時間0-2000毫秒
- int exeTime = new Random().nextInt(2000);
- System.out.println(name + "開始執行,預計執行時間= " + exeTime + "毫秒----------");
- Thread.sleep(exeTime);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- lock.release();
- }
- }
- }
鎖測試程式碼
Java程式碼- /**
- * 分散式鎖例項
- *
- * @author shencl
- */
- publicclass DistributedLockExample {
- privatestatic CuratorFramework client = ClientFactory.newClient();
- privatestaticfinal String PATH = "/locks";
- // 程序內部(可重入)讀寫鎖
- privatestaticfinal InterProcessReadWriteLock lock;
- // 讀鎖
- privatestaticfinal InterProcessLock readLock;
- // 寫鎖
- privatestaticfinal InterProcessLock writeLock;
- static {
- client.start();
- lock = new InterProcessReadWriteLock(client, PATH);
- readLock = lock.readLock();
- writeLock = lock.writeLock();
- }
- publicstaticvoid main(String[] args) {
- try {
- List<Thread> jobs = Lists.newArrayList();
- for (int i = 0; i < 10; i++) {
- Thread t = new Thread(new ParallelJob("Parallel任務" + i, readLock));
- jobs.add(t);
- }
- for (int i = 0; i < 10; i++) {
- Thread t = new Thread(new MutexJob("Mutex任務" + i, writeLock));
- jobs.add(t);
- }
- for (Thread t : jobs) {
- t.start();
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- CloseableUtils.closeQuietly(client);
- }
- }
- }
看到沒,用法和java concurrent包裡的ReentrantReadWriteLock 是一模一樣的。
事實上,整個recipes包的目錄結構、實現原理同java concurrent包的設定是很一致的。比如有queue,Semaphore,Barrier等類,。他整個就是模仿jdk的實現,只不過是基於分散式的!
後邊的幾項,Barriers(關卡),Atomic(原子量),Caches,Queues和java concurrent包裡的類的用法是一樣的,就不繼續貼了,有些附件裡有。
要說明的是:有的功能效能不是特別理想,網上也沒見有大的專案的使用案例。比如基於CAS機制的atomic,在某些情況重試的效率還不如硬同步,要是zookeeper節點再一多,各個節點之間通過event觸發的資料同步極其頻繁。那效能可以想象。
三、測試方法
curator提供了很好的測試工具,你甚至是可以在完全沒有搭建zookeeper server端的情況下,完成測試。
有2個重要的類
TestingServer 模擬單點, TestingCluster模擬叢集。
需要使用的話,得依賴
Xml程式碼- <dependency>
- <groupId>org.apache.curator</groupId>
- <artifactId>curator-test</artifactId>
- <version>2.5.0</version>
- </dependency>
全文完。
本文參考:
http://curator.apache.org/
http://www.cnblogs.com/hzhuxin/archive/2012/11/01/2749341.html
http://www.chengxuyuans.com/Java+/72042.html
http://macrochen.iteye.com/blog/1366136
相關推薦
Zookeeper分散式及客戶端Curator的API簡單使用
最近公司專案中使用了分散式Zookeeper及Dubbo,為了弄清楚這些框架在專案中的使用,在我業餘時間中學習了一些Zookeeper的簡單用法,分享出來,若有不足之處,望大家給與建議...... 一、什麼是分散式系統? 我的理解:將原有的系統拆分為多個子系統組成一個龐大的系統,這個龐大
Zookeeper(八)-zookeeper客戶端Curator
zookeeper的原生api相對來說比較繁瑣,比如:對節點新增監聽事件,當監聽觸發後,我們需要再次手動新增監聽,否則監聽只生效一次;再比如,斷線重連也需要我們手動程式碼來判斷處理等等。對於curator的介紹,從網上百度了一段:Curator是Netflix開源的一套zoo
7.5 zookeeper客戶端curator的基本使用
serve server 超時 one c-c tlist result 強制 car 使用zookeeper原生API實現一些復雜的東西比較麻煩。所以,出現了兩款比較好的開源客戶端,對zookeeper的原生API進行了包裝:zkClient和curator。後者是Net
zookeeper客戶端curator簡易使用
zookeeper客戶端curator簡易使用 寫在前面:目前Curator有2.x.x和3.x.x兩個系列的版本,支援不同版本的Zookeeper。其中Curator 2.x.x相容Zookeeper的3.4.x和3.5.x。而Curator 3.x.x只相容Zookeeper
zookeeper開源客戶端Curator介紹(六)
上一篇文章介紹了zookeeper原生API的使用,使用過原生API不得不說,有很多的問題,比如:不能遞迴建立和刪除節點、Watcher只能使用一次、還有很多可以解決分散式應用問題的api(比如分散式鎖,leader選舉等),但由於ZooKeeper提供的原始
zookeeper開源客戶端Curator典型應用場景之-服務註冊與發現(十一)
隨著業務增加,以前簡單的系統已經變得越來越複雜,單純的提升伺服器效能也不是辦法,而且程式碼也是越來越龐大,維護也變得越來越困難,這一切都催生了新的架構設計風格 – 微服務架構的出現。 微服務給我們帶來了很多好處,例如:獨立可擴充套件、易維護。但是隨著應用的分解
zookeeper開源客戶端Curator典型應用場景之-Barrier屏障(十三)
什麼是Barrier Barrier是這樣的:Barrier是一個同步點,每一個程序到達此點都要等待,直到某一個條件滿足,然後所有的節點繼續進行。 比如:賽跑大家都知道,所有比賽人員都會在起跑線外等待,直到教練員的槍響之後,所有參賽者立刻開始賽跑。 JDK的併
ZooKeeper的Java客戶端工具使用(Curator)
安裝 <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-client</artifactId> <vers
Zookeeper客戶端Curator使用指南
what is Curator ? Curator是zookeeper分散式協調服務的java客戶端庫,它包裝了一系列操作zk的高階API和實用庫,是的操作zk變得更加容易和可靠。例如使用原生zk的API實現分散式鎖的話,程式碼量多,複雜,使用Curator
zookeeper開源客戶端Curator典型應用場景之-分散式計數器(十四)
之前我們瞭解了基於Corator的分散式鎖之後,我們就很容易基於其實現一個分散式計數器,顧名思義,計數器是用來計數的, 利用ZooKeeper可以實現一個叢集共享的計數器。 只要使用相同的path就可以得到最新的計數器值, 這是由ZooKeeper的一致性保證
Zookeeper開源客戶端Curator之基本功能講解
簡介 Curator是Netflix公司開源的一套Zookeeper客戶端框架。瞭解過Zookeeper原生API都會清楚其複雜度。Curator幫助我們在其基礎上進行封裝、實現一些開發細節,包括接連重連、反覆註冊Watcher和NodeExistsExcept
Zookeeper客戶端Curator使用詳解
前提 最近剛好用到了zookeeper,做了一個基於SpringBoot、Curator、Bootstrap寫了一個視覺化的Web應用: 歡迎使用和star。 簡介 Curator是Netflix公司開源的一套zookeeper客戶端框架,解決了很多Zookeep
ZooKeeper客戶端curator元件介紹
Curator framework提供了高階API, 極大的簡化了ZooKeeper的使用。 它在ZooKeeper基礎上增加了很多特性,可以管理與ZOoKeeper的連線和重試機制。這些特性包括: 自動連線管理 ** 有些潛在的錯誤情況需要讓ZooKeeper client重建連線和重試。Curato
Zookeeper客戶端Curator使用介紹
簡介 Curator是Netflix公司開源的一套zookeeper客戶端框架,解決了很多Zookeeper客戶端非常底層的細節開發工作,包括連線重連、反覆註冊Watcher和NodeExistsException異常等等。Patrixck Hunt(Zook
zookeeper開源客戶端Curator典型應用場景之-訊息佇列(十二)
Curator框架也有分散式佇列實現。 利用ZK的PERSISTENT SEQUENTIAL(持久順序)節點,可以保證放入到佇列中的專案是按照順序排隊的。並且宕機重啟並不丟失訊息, 如果單一的消費者從佇列中取資料, 那麼它是先入先出的,這也是佇列的特點。 如果
zookeeper開源客戶端Curator典型應用場景之-Master選舉(十)
在生產環境中,一般要保證服務的高可用,有時候只需要選出一臺機器來執行,其餘機器處於備用狀態,比如,在分散式系統中很常見的一個問題就是定時任務的執行。如果多臺機器同時執行相同的定時任務,業務複雜則可能出現災難性的後果。我使用的是噹噹網的elastic-job分散
zookeeper總結之客戶端執行核心模塊
except pre 執行 strong main amp per bst ply ZooKeeper ZooKeeper是客戶端操作ZooKeeper服務端的核心類。當用戶向ZooKeeperMain執行相關命令時,最終會交給ZooKeeper執行,其會將用戶請求封裝
zookeeper叢集的客戶端與伺服器端
zookeeper服務端命令: 啟動命令:sh zkServer.sh start 停止命令:sh zkServer.sh stop zookeeper客戶端命令: 啟動命令:sh zkCli.sh 連線其他客戶端:sh zkCli.sh -server ip:port  
分享兩個zookeeper 視覺化客戶端工具( ZooInspector ZooViewer )
前言 這年頭,下點工具各種收費、 各種積分。話不多說,先上乾貨。 1. ZooInspector 百度網盤 https://pan.baidu.com/s/1ImYCP3YMwQK8qjLY5ihwuA?fid=7633191291153
zookeeper 原始碼:客戶端連線過程
可能我們直接使用 zookeeper 的機會並不多,甚至都不會直接去使用,但是 zookeeper 作為分散式協調框架,在如今分散式系統領域有著非常大的作用,很多流行框架都有使用它,如分散式治理框架 dubbo,大資料領域中的 hbase,所以瞭解 zookee