SpringBoot整合Zookeeper詳細(xì)教程
一、引言
使用原生的zookeeper時(shí)候會(huì)遇到watcher一次注冊(cè)生效一次等情況,因此使用curator
curator是Netflix公司開源的一個(gè) zookeeper客戶端原生API接口上進(jìn)行了包裝,解決了很多問題并提供Zookeeper分布式鎖服務(wù)、集群領(lǐng)導(dǎo)選舉、共享計(jì)數(shù)器、緩存機(jī)制、分布式隊(duì)列等的應(yīng)用的抽象封裝
二、引入依賴
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.6.2</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>5.2.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>5.2.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>2.0.10</version> </dependency>
三、編寫客戶端
要改Windows的host文件。host文件位置是C:\Windows\System32\drivers\etc
3.1、ZookeeperConfig
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.retry.ExponentialBackoffRetry; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class ZookeeperConfig { //集群地址,分割不能有空格 在程序里寫connectString不可使用ip,必須使用主機(jī)名 private String connectString = "master:2181,slave1:2181,slave2:2181"; //連接超時(shí)時(shí)間 private int sessionTimeout = 5000; //會(huì)話存活時(shí)間,根據(jù)業(yè)務(wù)靈活指定 private Integer sessionTimeOut=5000; //重試機(jī)制時(shí)間參數(shù) private Integer sleepMsBetweenRetry=1000; //重試機(jī)制重試次數(shù) private Integer maxRetries=3; //命名空間(父節(jié)點(diǎn)名稱) private String namespace=""; /** - `session`重連策略 - `RetryPolicy retry Policy = new RetryOneTime(3000);` - 說明:三秒后重連一次,只重連一次 - `RetryPolicy retryPolicy = new RetryNTimes(3,3000);` - 說明:每三秒重連一次,重連三次 - `RetryPolicy retryPolicy = new RetryUntilElapsed(1000,3000);` - 說明:每三秒重連一次,總等待時(shí)間超過個(gè)`10`秒后停止重連 - `RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3)` - 說明:這個(gè)策略的重試間隔會(huì)越來越長(zhǎng) - 公式:`baseSleepTImeMs * Math.max(1,random.nextInt(1 << (retryCount + 1)))` - `baseSleepTimeMs` = `1000` 例子中的值 - `maxRetries` = `3` 例子中的值 */ @Bean("curatorClient") public CuratorFramework curatorClient() throws Exception { CuratorFramework client = CuratorFrameworkFactory.builder() .connectString(connectString) .connectionTimeoutMs(sessionTimeout) .sessionTimeoutMs(sessionTimeOut) //session重連策略 .retryPolicy(new ExponentialBackoffRetry(sleepMsBetweenRetry,maxRetries)) //設(shè)置命名空間 在操作節(jié)點(diǎn)的時(shí)候,會(huì)以這個(gè)為父節(jié)點(diǎn) .namespace(namespace) .build(); client.start(); //注冊(cè)監(jiān)聽器 ZookeeperWatches watches = new ZookeeperWatches(client); watches.znodeWatcher(); watches.znodeChildrenWatcher(); return client; } }
3.2、ZookeeperWatches
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.recipes.cache.*; import org.apache.zookeeper.data.Stat; public class ZookeeperWatches { private CuratorFramework client; public ZookeeperWatches(CuratorFramework client) { this.client = client; } public void znodeWatcher() throws Exception { NodeCache nodeCache = new NodeCache(client, "/"); nodeCache.start(); nodeCache.getListenable().addListener(new NodeCacheListener() { @Override public void nodeChanged() throws Exception { System.out.println("=======節(jié)點(diǎn)改變==========="); String path = nodeCache.getPath(); String currentDataPath = nodeCache.getCurrentData().getPath(); String currentData = new String(nodeCache.getCurrentData().getData()); Stat stat = nodeCache.getCurrentData().getStat(); System.out.println("path:"+path); System.out.println("currentDataPath:"+currentDataPath); System.out.println("currentData:"+currentData); } }); System.out.println("節(jié)點(diǎn)監(jiān)聽注冊(cè)完成"); } public void znodeChildrenWatcher() throws Exception { PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/",true); pathChildrenCache.start(); pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() { @Override public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { System.out.println("=======節(jié)點(diǎn)子節(jié)點(diǎn)改變==========="); PathChildrenCacheEvent.Type type = event.getType(); String childrenData = new String(event.getData().getData()); String childrenPath = event.getData().getPath(); Stat childrenStat = event.getData().getStat(); System.out.println("子節(jié)點(diǎn)監(jiān)聽類型:"+type); System.out.println("子節(jié)點(diǎn)路徑:"+childrenPath); System.out.println("子節(jié)點(diǎn)數(shù)據(jù):"+childrenData); System.out.println("子節(jié)點(diǎn)元數(shù)據(jù):"+childrenStat); } }); System.out.println("子節(jié)點(diǎn)監(jiān)聽注冊(cè)完成"); } }
3.3、ZookeeperController
@RestController @RequestMapping(value = "/zookeeper") public class ZookeeperController { @Resource(name = "curatorClient") private CuratorFramework client; @RequestMapping("/createZnode") public String createZnode(){ String path = "/nacl"; String data = "shuaige"; List<ACL> aclList = new ArrayList<>(); Id id = new Id("world", "anyone"); aclList.add(new ACL(ZooDefs.Perms.ALL, id)); try { client.create() .creatingParentsIfNeeded() //沒有父節(jié)點(diǎn)時(shí) 創(chuàng)建父節(jié)點(diǎn) .withMode(CreateMode.PERSISTENT) //節(jié)點(diǎn)類型 .withACL(aclList) //配置權(quán)限 .forPath(path, data.getBytes()); } catch (Exception e) { e.printStackTrace(); return "節(jié)點(diǎn)創(chuàng)建失敗"+e.getMessage(); } return "節(jié)點(diǎn)創(chuàng)建成功"; } @RequestMapping("/selectZnode") public String selectZnode(){ HashMap<String,String> hashMap=new HashMap(); String path="/nacl"; Stat stat; try { stat = client.checkExists().forPath(path); if (stat == null) { hashMap.put("Error","不存在該節(jié)點(diǎn)"); } String dataString = new String(client.getData().forPath(path)); hashMap.put(path, dataString); hashMap.put("stat", stat.toString()); } catch (Exception e) { e.printStackTrace(); } return JSON.toJSONString(hashMap); } @RequestMapping("/selectChildrenZnode") public String selectChildrenZnode(){ Map<String, String> hashMap = new HashMap<>(); String path="/"; try { List<String> list = client.getChildren().forPath(path); for (String s : list) { String dataString = new String(client.getData().forPath(path+s)); hashMap.put(path+s, dataString); } } catch (Exception e) { e.printStackTrace(); } return JSON.toJSONString(hashMap); } @RequestMapping("/setData") public String setData() { String path="/nacl"; String data="big"; Integer version=0; HashMap<String,String> hashMap=new HashMap<>(); try { Stat stat = client.setData().withVersion(version).forPath(path, data.getBytes()); hashMap.put("success", "修改成功"); hashMap.put("version", String.valueOf(stat.getVersion())); } catch (Exception e) { e.printStackTrace(); hashMap.put("error", "修改失敗:"+e.getMessage()); } return JSON.toJSONString(hashMap); } @RequestMapping("/delete") public String delete() { HashMap<String,String> hashMap=new HashMap<>(); String path="/nacl"; String data="big"; Integer version=1; try { client.delete().withVersion(version).forPath(path); hashMap.put("success", "刪除成功"); } catch (Exception e) { e.printStackTrace(); hashMap.put("error", "刪除失敗:"+e.getMessage()); } return JSON.toJSONString(hashMap); } @RequestMapping("/createAsyncZnode") public String createAsyncZnode(){ String path = "/nacl"; String data = "shuaige"; try { client.create() .creatingParentsIfNeeded() .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) //異步回調(diào) 增刪改都有異步方法 .inBackground(new BackgroundCallback() { @Override public void processResult(CuratorFramework client, CuratorEvent event) throws Exception { System.out.println("異步回調(diào)--獲取權(quán)限:"+client.getACL().forPath(path)); System.out.println("異步回調(diào)--獲取數(shù)據(jù):"+new String(client.getData().forPath(path))); System.out.println("異步回調(diào)--獲取事件名稱:"+event.getName()); System.out.println("異步回調(diào)--獲取事件類型:"+event.getType()); } }) .forPath(path, data.getBytes()); } catch (Exception e) { e.printStackTrace(); return "節(jié)點(diǎn)創(chuàng)建失敗"+e.getMessage(); } return "節(jié)點(diǎn)創(chuàng)建成功"; } }
到此這篇關(guān)于SpringBoot整合Zookeeper詳細(xì)教程的文章就介紹到這了,更多相關(guān)SpringBoot整合Zookeeper內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 淺談Java(SpringBoot)基于zookeeper的分布式鎖實(shí)現(xiàn)
- 使用dubbo+zookeeper+spring boot構(gòu)建服務(wù)的方法詳解
- SpringBoot中dubbo+zookeeper實(shí)現(xiàn)分布式開發(fā)的應(yīng)用詳解
- SpringBoot集成Curator實(shí)現(xiàn)Zookeeper基本操作的代碼示例
- SpringBoot系列教程之dubbo和Zookeeper集成方法
- SpringBoot整合Dubbo+Zookeeper實(shí)現(xiàn)RPC調(diào)用
- springboot應(yīng)用訪問zookeeper的流程
- Java Spring Boot 集成Zookeeper
- SpringBoot讀取ZooKeeper(ZK)屬性的方法實(shí)現(xiàn)
相關(guān)文章
淺談HTTP使用BASIC認(rèn)證的原理及實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄獪\談HTTP使用BASIC認(rèn)證的原理及實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11深入解析Java編程中面向字節(jié)流的一些應(yīng)用
這篇文章主要介紹了Java編程中面向字節(jié)流的一些應(yīng)用,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-10-10劍指Offer之Java算法習(xí)題精講鏈表與字符串及數(shù)組
跟著思路走,之后從簡(jiǎn)單題入手,反復(fù)去看,做過之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化2022-03-03Java集成Onlyoffice的示例代碼及場(chǎng)景分析
這篇文章主要介紹了Java集成Onlyoffice的示例代碼及場(chǎng)景分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2025-05-05Java批量從svn導(dǎo)出多個(gè)項(xiàng)目代碼實(shí)例
這篇文章主要介紹了java批量從svn導(dǎo)出多個(gè)項(xiàng)目代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03Java報(bào)錯(cuò)狀態(tài)碼快速定位與解決方法
在日常開發(fā)中Java程序員最頭疼的問題之一就是遇到各種報(bào)錯(cuò)狀態(tài)碼,這些狀態(tài)碼就像謎語一樣讓人摸不著頭腦,比如突然蹦出一個(gè)500或者404,新手可能會(huì)直接懵掉,別擔(dān)心!這篇文章會(huì)帶你徹底搞懂Java報(bào)錯(cuò)狀態(tài)碼的來龍去脈,需要的朋友可以參考下2025-05-05java -D參數(shù)設(shè)置系統(tǒng)屬性無效問題及解決
這篇文章主要介紹了java -D參數(shù)設(shè)置系統(tǒng)屬性無效問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12