SpringBoot整合Zookeeper詳細(xì)教程
一、引言
使用原生的zookeeper時(shí)候會(huì)遇到watcher一次注冊(cè)生效一次等情況,因此使用curator
curator是Netflix公司開(kāi)源的一個(gè) zookeeper客戶(hù)端原生API接口上進(jìn)行了包裝,解決了很多問(wèn)題并提供Zookeeper分布式鎖服務(wù)、集群領(lǐng)導(dǎo)選舉、共享計(jì)數(shù)器、緩存機(jī)制、分布式隊(duì)列等的應(yīng)用的抽象封裝
二、引入依賴(lài)
<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>
三、編寫(xiě)客戶(hù)端
要改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 {
//集群地址,分割不能有空格 在程序里寫(xiě)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)名稱(chēng))
private String namespace="";
/**
- `session`重連策略
- `RetryPolicy retry Policy = new RetryOneTime(3000);`
- 說(shuō)明:三秒后重連一次,只重連一次
- `RetryPolicy retryPolicy = new RetryNTimes(3,3000);`
- 說(shuō)明:每三秒重連一次,重連三次
- `RetryPolicy retryPolicy = new RetryUntilElapsed(1000,3000);`
- 說(shuō)明:每三秒重連一次,總等待時(shí)間超過(guò)個(gè)`10`秒后停止重連
- `RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3)`
- 說(shuō)明:這個(gè)策略的重試間隔會(huì)越來(lái)越長(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)聽(tīng)器
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)聽(tīng)注冊(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)聽(tīng)類(lèi)型:"+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)聽(tīng)注冊(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() //沒(méi)有父節(jié)點(diǎn)時(shí) 創(chuàng)建父節(jié)點(diǎn)
.withMode(CreateMode.PERSISTENT) //節(jié)點(diǎn)類(lèi)型
.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)--獲取事件名稱(chēng):"+event.getName());
System.out.println("異步回調(diào)--獲取事件類(lèi)型:"+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)分布式開(kāi)發(fā)的應(yīng)用詳解
- SpringBoot集成Curator實(shí)現(xiàn)Zookeeper基本操作的代碼示例
- SpringBoot系列教程之dubbo和Zookeeper集成方法
- SpringBoot整合Dubbo+Zookeeper實(shí)現(xiàn)RPC調(diào)用
- springboot應(yīng)用訪問(wèn)zookeeper的流程
- Java Spring Boot 集成Zookeeper
- SpringBoot讀取ZooKeeper(ZK)屬性的方法實(shí)現(xiàn)
相關(guān)文章
淺談HTTP使用BASIC認(rèn)證的原理及實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇淺談HTTP使用BASIC認(rèn)證的原理及實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11
深入解析Java編程中面向字節(jié)流的一些應(yīng)用
這篇文章主要介紹了Java編程中面向字節(jié)流的一些應(yīng)用,是Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-10-10
劍指Offer之Java算法習(xí)題精講鏈表與字符串及數(shù)組
跟著思路走,之后從簡(jiǎn)單題入手,反復(fù)去看,做過(guò)之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化2022-03-03
Java集成Onlyoffice的示例代碼及場(chǎng)景分析
這篇文章主要介紹了Java集成Onlyoffice的示例代碼及場(chǎng)景分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2025-05-05
Java批量從svn導(dǎo)出多個(gè)項(xiàng)目代碼實(shí)例
這篇文章主要介紹了java批量從svn導(dǎo)出多個(gè)項(xiàng)目代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
Java報(bào)錯(cuò)狀態(tài)碼快速定位與解決方法
在日常開(kāi)發(fā)中Java程序員最頭疼的問(wèn)題之一就是遇到各種報(bào)錯(cuò)狀態(tài)碼,這些狀態(tài)碼就像謎語(yǔ)一樣讓人摸不著頭腦,比如突然蹦出一個(gè)500或者404,新手可能會(huì)直接懵掉,別擔(dān)心!這篇文章會(huì)帶你徹底搞懂Java報(bào)錯(cuò)狀態(tài)碼的來(lái)龍去脈,需要的朋友可以參考下2025-05-05
java -D參數(shù)設(shè)置系統(tǒng)屬性無(wú)效問(wèn)題及解決
這篇文章主要介紹了java -D參數(shù)設(shè)置系統(tǒng)屬性無(wú)效問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12

