javascript
SpringBoot2 整合 Zookeeper组件,管理架构中服务协调
本文源碼:GitHub·點(diǎn)這里 || GitEE·點(diǎn)這里
一、Zookeeper基礎(chǔ)簡介
1、概念簡介
Zookeeper是一個(gè)Apache開源的分布式的應(yīng)用,為系統(tǒng)架構(gòu)提供協(xié)調(diào)服務(wù)。從設(shè)計(jì)模式角度來審視:該組件是一個(gè)基于觀察者模式設(shè)計(jì)的框架,負(fù)責(zé)存儲和管理數(shù)據(jù),接受觀察者的注冊,一旦數(shù)據(jù)的狀態(tài)發(fā)生變化,Zookeeper就將負(fù)責(zé)通知已經(jīng)在Zookeeper上注冊的觀察者做出相應(yīng)的反應(yīng),從而實(shí)現(xiàn)集群中類似Master/Slave管理模式。ZooKeeper的目標(biāo)就是封裝好復(fù)雜易出錯(cuò)的關(guān)鍵服務(wù),將簡單易用的接口和性能高效、功能穩(wěn)定的系統(tǒng)提供給用戶。
2、基本理論
- 數(shù)據(jù)結(jié)構(gòu)
ZooKeeper記錄數(shù)據(jù)的結(jié)構(gòu)與Linux文件系統(tǒng)相似,整體可以看作一棵樹,每個(gè)節(jié)點(diǎn)稱ZNode。每個(gè)Znode默認(rèn)能夠存儲1MB的數(shù)據(jù),每個(gè)ZNode都可以通過其路徑唯一標(biāo)識。
- 節(jié)點(diǎn)類型
短暫(ephemeral):客戶端和服務(wù)器端斷開連接后,創(chuàng)建的節(jié)點(diǎn)自動(dòng)刪除。
持久(persistent):客戶端和服務(wù)器端斷開連接后,創(chuàng)建的節(jié)點(diǎn)持久化保存。
- 集群服務(wù)
在Zookeeper集群服務(wù)是由一個(gè)領(lǐng)導(dǎo)者(leader),多個(gè)跟隨者(follower)組成的集群。領(lǐng)導(dǎo)者負(fù)責(zé)進(jìn)行投票的發(fā)起和決議,更新集群服務(wù)狀態(tài)。跟隨者用于接收客戶請求并向客戶端返回結(jié)果,在選舉Leader過程中參與投票。集群中只要有半數(shù)以上節(jié)點(diǎn)存活,Zookeeper集群就能正常服務(wù)。
- 數(shù)據(jù)一致性
每個(gè)server保存一份相同的數(shù)據(jù)拷貝,客戶端無論請求到被集群中哪個(gè)server處理,得到的數(shù)據(jù)都是一致的。
3、應(yīng)用場景
- 經(jīng)典應(yīng)用:Dubbo框架的服務(wù)注冊和發(fā)現(xiàn);
- 分布式消息同步和協(xié)調(diào)機(jī)制;
- 服務(wù)器節(jié)點(diǎn)動(dòng)態(tài)上下線;
- 統(tǒng)一配置管理、負(fù)載均衡、集群管理;
二、安全管理操作
1、操作權(quán)限
ZooKeeper的節(jié)點(diǎn)有5種操作權(quán)限:CREATE(增)、READ(查)、WRITE(改)、DELETE(刪)、ADMIN(管理)等相關(guān)權(quán)限,這5種權(quán)限集合可以簡寫為crwda,每個(gè)單詞的首字符拼接而成。
2、認(rèn)證方式:
- world
默認(rèn)方式,開放的權(quán)限,意解為全世界都能隨意訪問。
- auth
已經(jīng)授權(quán)且認(rèn)證通過的用戶才可以訪問。
- digest
用戶名:密碼方式認(rèn)證,實(shí)際業(yè)務(wù)開發(fā)中最常用的方式。
- IP白名單
授權(quán)指定的Ip地址,和指定的權(quán)限點(diǎn),控制訪問。
3、Digest授權(quán)流程
- 添加認(rèn)證用戶
addauth digest 用戶名:密碼
- 設(shè)置權(quán)限
setAcl /path auth:用戶名:密碼:權(quán)限
- 查看Acl設(shè)置
getAcl /path
- 完整操作流程
三、整合 SpringBoot2 框架
1、核心依賴
Curator是Apache開源的一個(gè)Zookeeper客戶端連接和操作的組件,Curator框架在Zookeeper原生API接口上進(jìn)行二次包裝。提供ZooKeeper各種應(yīng)用場景:比如:分布式鎖服務(wù)、集群領(lǐng)導(dǎo)選舉、共享計(jì)數(shù)器、緩存機(jī)制、分布式隊(duì)列等API封裝。
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>2.12.0</version> </dependency> <dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>2.12.0</version> </dependency> <dependency><groupId>org.apache.curator</groupId><artifactId>curator-client</artifactId><version>2.12.0</version> </dependency>2、Zookeeper參數(shù)
zoo:keeper:#開啟標(biāo)志enabled: true#服務(wù)器地址server: 127.0.0.1:2181#命名空間,被稱為ZNodenamespace: cicada#權(quán)限控制,加密digest: smile:123456#會話超時(shí)時(shí)間sessionTimeoutMs: 3000#連接超時(shí)時(shí)間connectionTimeoutMs: 60000#最大重試次數(shù)maxRetries: 2#初始休眠時(shí)間baseSleepTimeMs: 10003、服務(wù)初始化配置
@Configuration public class ZookeeperConfig {private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperConfig.class) ;@Resourceprivate ZookeeperParam zookeeperParam ;private static CuratorFramework client = null ;/*** 初始化*/@PostConstructpublic void init (){//重試策略,初試時(shí)間1秒,重試10次RetryPolicy policy = new ExponentialBackoffRetry(zookeeperParam.getBaseSleepTimeMs(),zookeeperParam.getMaxRetries());//通過工廠創(chuàng)建Curatorclient = CuratorFrameworkFactory.builder().connectString(zookeeperParam.getServer()).authorization("digest",zookeeperParam.getDigest().getBytes()).connectionTimeoutMs(zookeeperParam.getConnectionTimeoutMs()).sessionTimeoutMs(zookeeperParam.getSessionTimeoutMs()).retryPolicy(policy).build();//開啟連接client.start();LOGGER.info("zookeeper 初始化完成...");}public static CuratorFramework getClient (){return client ;}public static void closeClient (){if (client != null){client.close();}} }4、封裝系列接口
public interface ZookeeperService {/*** 判斷節(jié)點(diǎn)是否存在*/boolean isExistNode (final String path) ;/*** 創(chuàng)建節(jié)點(diǎn)*/void createNode (CreateMode mode,String path ) ;/*** 設(shè)置節(jié)點(diǎn)數(shù)據(jù)*/void setNodeData (String path, String nodeData) ;/*** 創(chuàng)建節(jié)點(diǎn)*/void createNodeAndData (CreateMode mode, String path , String nodeData) ;/*** 獲取節(jié)點(diǎn)數(shù)據(jù)*/String getNodeData (String path) ;/*** 獲取節(jié)點(diǎn)下數(shù)據(jù)*/List<String> getNodeChild (String path) ;/*** 是否遞歸刪除節(jié)點(diǎn)*/void deleteNode (String path,Boolean recursive) ;/*** 獲取讀寫鎖*/InterProcessReadWriteLock getReadWriteLock (String path) ; }5、接口實(shí)現(xiàn)
@Service public class ZookeeperServiceImpl implements ZookeeperService {private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperServiceImpl.class);@Overridepublic boolean isExistNode(String path) {CuratorFramework client = ZookeeperConfig.getClient();client.sync() ;try {Stat stat = client.checkExists().forPath(path);return client.checkExists().forPath(path) != null;} catch (Exception e) {LOGGER.error("isExistNode error...", e);e.printStackTrace();}return false;}@Overridepublic void createNode(CreateMode mode, String path) {CuratorFramework client = ZookeeperConfig.getClient() ;try {// 遞歸創(chuàng)建所需父節(jié)點(diǎn)client.create().creatingParentsIfNeeded().withMode(mode).forPath(path);} catch (Exception e) {LOGGER.error("createNode error...", e);e.printStackTrace();}}@Overridepublic void setNodeData(String path, String nodeData) {CuratorFramework client = ZookeeperConfig.getClient() ;try {// 設(shè)置節(jié)點(diǎn)數(shù)據(jù)client.setData().forPath(path, nodeData.getBytes("UTF-8"));} catch (Exception e) {LOGGER.error("setNodeData error...", e);e.printStackTrace();}}@Overridepublic void createNodeAndData(CreateMode mode, String path, String nodeData) {CuratorFramework client = ZookeeperConfig.getClient() ;try {// 創(chuàng)建節(jié)點(diǎn),關(guān)聯(lián)數(shù)據(jù)client.create().creatingParentsIfNeeded().withMode(mode).forPath(path,nodeData.getBytes("UTF-8"));} catch (Exception e) {LOGGER.error("createNode error...", e);e.printStackTrace();}}@Overridepublic String getNodeData(String path) {CuratorFramework client = ZookeeperConfig.getClient() ;try {// 數(shù)據(jù)讀取和轉(zhuǎn)換byte[] dataByte = client.getData().forPath(path) ;String data = new String(dataByte,"UTF-8") ;if (StringUtils.isNotEmpty(data)){return data ;}}catch (Exception e) {LOGGER.error("getNodeData error...", e);e.printStackTrace();}return null;}@Overridepublic List<String> getNodeChild(String path) {CuratorFramework client = ZookeeperConfig.getClient() ;List<String> nodeChildDataList = new ArrayList<>();try {// 節(jié)點(diǎn)下數(shù)據(jù)集nodeChildDataList = client.getChildren().forPath(path);} catch (Exception e) {LOGGER.error("getNodeChild error...", e);e.printStackTrace();}return nodeChildDataList;}@Overridepublic void deleteNode(String path, Boolean recursive) {CuratorFramework client = ZookeeperConfig.getClient() ;try {if(recursive) {// 遞歸刪除節(jié)點(diǎn)client.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);} else {// 刪除單個(gè)節(jié)點(diǎn)client.delete().guaranteed().forPath(path);}} catch (Exception e) {LOGGER.error("deleteNode error...", e);e.printStackTrace();}}@Overridepublic InterProcessReadWriteLock getReadWriteLock(String path) {CuratorFramework client = ZookeeperConfig.getClient() ;// 寫鎖互斥、讀寫互斥InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, path);return readWriteLock ;} }6、基于Swagger2接口
@Api("Zookeeper接口管理") @RestController public class ZookeeperApi {@Resourceprivate ZookeeperService zookeeperService ;@ApiOperation(value="查詢節(jié)點(diǎn)數(shù)據(jù)")@GetMapping("/getNodeData")public String getNodeData (String path) {return zookeeperService.getNodeData(path) ;}@ApiOperation(value="判斷節(jié)點(diǎn)是否存在")@GetMapping("/isExistNode")public boolean isExistNode (final String path){return zookeeperService.isExistNode(path) ;}@ApiOperation(value="創(chuàng)建節(jié)點(diǎn)")@GetMapping("/createNode")public String createNode (CreateMode mode, String path ){zookeeperService.createNode(mode,path) ;return "success" ;}@ApiOperation(value="設(shè)置節(jié)點(diǎn)數(shù)據(jù)")@GetMapping("/setNodeData")public String setNodeData (String path, String nodeData) {zookeeperService.setNodeData(path,nodeData) ;return "success" ;}@ApiOperation(value="創(chuàng)建并設(shè)置節(jié)點(diǎn)數(shù)據(jù)")@GetMapping("/createNodeAndData")public String createNodeAndData (CreateMode mode, String path , String nodeData){zookeeperService.createNodeAndData(mode,path,nodeData) ;return "success" ;}@ApiOperation(value="遞歸獲取節(jié)點(diǎn)數(shù)據(jù)")@GetMapping("/getNodeChild")public List<String> getNodeChild (String path) {return zookeeperService.getNodeChild(path) ;}@ApiOperation(value="是否遞歸刪除節(jié)點(diǎn)")@GetMapping("/deleteNode")public String deleteNode (String path,Boolean recursive) {zookeeperService.deleteNode(path,recursive) ;return "success" ;} }四、源代碼地址
GitHub·地址 https://github.com/cicadasmile/middle-ware-parent GitEE·地址 https://gitee.com/cicadasmile/middle-ware-parent總結(jié)
以上是生活随笔為你收集整理的SpringBoot2 整合 Zookeeper组件,管理架构中服务协调的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 这个生日有点冷!!
- 下一篇: RH033 Unit 2 Linux U