Zookeeper入門與實戰
ZooKeeper基本概念
Zookeeper是用於構建分散式系統的協調程式,可用於分散式系統的叢集監控、配置管理、構建分散式鎖等。 Zookeeper完全由Java編寫,客戶端有Java和C版本。 下面介紹ZooKeeper的核心概念。
ZNode
ZooKeeper類似一個遠端檔案系統,根節點為"/"。這個檔案系統由稱為znode的節點組成,每個znode包含path和data。 有4種類型的znode:
- EPHEMERAL 臨時節點,在session期間有效,因此臨時節點無法建立孩子節點。
- EPHEMERAL_SEQUENTIAL 臨時序列節點,會在末尾新增序號,格式為%010,從1,位數不足10位在前面補0,最小的序號由父節點保持。
- PERSISTENT 永久節點,將序列化到Zookeeper伺服器
- PERSISTENT_SEQUENTIAL 永久序列節點
Watcher
watcher是監聽器的意思,zookeeper客戶端可以對znode設定Watcher,當znode狀態變化時,zookeeper伺服器會對設定了Watcher的客戶端傳送通知。
ZooKeeper安裝
執行環境
- Linux系統
- Java執行環境
安裝步驟
- 解壓zookeeper-3.4.13.tar.gz
- 配置檔案
conf目錄下存放了zookeeper相關的配置檔案:
初始的時候,zoo.cfg檔案不存在,只存在模板檔案zoo_sample.cfg。
通過mv或cp命令,得到zoo.cfg,編輯檔案內容如下:
zookeeper實際上支援叢集配置,初始情況下我們配置單機版。
重要的配置項:
dataDir:zookeeper資料存放的資料夾,需要預先建立
clientPort:zookeeper服務埠,客戶端通過該埠與zookeeper通訊
此外,log4j.properties
- 啟動ZooKeeper 命令列執行 bin/zkServer.sh start,啟動ZooKeeper服務。
至此,ZooKeeper單機部署完成。
bin/zkCli.sh 是zookeeper內建的客戶端,可通過命令列操作zookeeper。
- 啟動客戶端 zookeeper根目錄下,命令列輸入 bin/zkCli.sh啟動客戶端。
- 客戶端命令簡介
命令 | 作用 |
---|---|
ls path | 列出path下所有子節點 |
create path data | 建立路徑為path的節點,節點上附帶資料data |
get path | 獲取路徑為path的節點的資料 |
set path data | 設定path節點的資料為data |
delete path | 刪除節點 |
下面是執行結果:
ZooKeeper Java客戶端
API介紹
ZooKeeper
方法 | 說明 |
---|---|
ZooKeeper(String connectString, int sessionTimeout, Watcher watcher) | connectionString:分隔的多個ip:port;watcher:一個預設的watcher |
Stat exists(final String path, Watcher watcher) | 檢查節點是否存在,並在節點上設定Watcher,返回Stat,包含節點的狀態資訊,如果為null表示節點不存在 |
String create(final String path, byte data[], List acl, CreateMode createMode) | 建立節點,可通過ACL設定節點訪問許可權,CreateMode指定節點型別 |
byte[] getData(final String path, Watcher watcher, Stat stat) | 獲取節點資料,並在節點上設定Watcher,如果傳入了非空的Stat物件,則通過該Stat物件返回節點狀態資訊 |
Stat setData(final String path, byte data[], int version) | 設定節點資料,version代表版本號,如果傳入的版本號和ZooKeeper伺服器上該節點版本號不一致,更新失敗。特別地,傳入-1將忽略版本號校驗。 |
void delete(final String path, int version) | 刪除節點,存在子節點時,父節點無法刪除 |
List getChildren(final String path, Watcher watcher) | 獲取當前節點下所有孩子節點,不遞迴 |
CreateMode 節點型別:
型別 | 說明 |
---|---|
PERSISTENT | 永久節點 |
PERSISTENT_SEQUENTIAL | 永久序列節點 |
EPHEMERAL | 臨時節點 |
EPHEMERAL_SEQUENTIAL | 臨時序列節點 |
Watcher 監聽器介面,客戶端可以在指定節點上註冊Watcher,當相應事件發生時,ZooKeeper伺服器會將事件傳送到客戶端,從而觸發Watcher。
方法 | 說明 |
---|---|
void process(WatchedEvent event) | 事件處理介面 |
Watcher註冊方式
- ZooKeeper.exists
- ZooKeeper.getData
- ZooKeeper.getChildren 注意: Watcher是一次性的,被觸發過後將失效,需要重新註冊
Watcher事件型別 通過 exists、getData、getChildren三個方法註冊的Watcher,共涉及以下4中事件型別:
- Create event(節點建立) exists方法註冊的Watcher可被此事件觸發
- Deleted event(節點刪除) exists、getData、getChildren 三個方法註冊的Watcher都會被觸發
- Changed event(節點更新) exists、getData註冊的Watcher將被觸發
- Child event(孩子節點變動) getChildren註冊的Watcher將被觸發
maven依賴
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.13</version>
</dependency>
Curd示例
有幾點需要注意:
- ZooKeeper建立連線的過程是非同步的 這裡使用CountdownLatch確保連線建立完成後,再使用客戶端執行其他操作
- ZooKeeper對子節點的管理是非遞迴的 如以下節點樹: /root /root/child1 /root/child1/child2 獲取 /root 節點的孩子節點,只能獲取到 /root/child1 這個特點導致以下結果: 不能先刪除父節點,create方法不能遞迴建立子節點
package org.lin.zkp;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
/**
* Zookeeper入門示例
* 1.檢查節點是否存在
* 2.不存在建立節點
* 3.修改節點資料
* 4.刪除節點
*
*/
public class Curd {
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
ZooKeeper zk = new ZooKeeper("192.168.142.128:2181", 5000,
new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("default event handler:" + event);
latch.countDown();
}
},
false);
//使用countDownLatch等待連線建立,因為zookeeper建立連線的過程是非同步的,不等待下面的操作可能丟擲異常
latch.await();
System.out.println("連線建立完成");
System.out.println("列印連線資訊");
System.out.println("zkSessionId:" + zk.getSessionId());
System.out.println("zkSessionPassword:" + toHexString(zk.getSessionPasswd()));
System.out.println("zkSessionTimeout:" + zk.getSessionTimeout());
System.out.println("zkState:" + zk.getState());
//可以在該節點掛載一個Watcher,在節點資料更新、節點被刪除時,Watcher被觸發,隨後移除
Stat stat = zk.exists("/parent", new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("changed since exist check:" + event);
}
});
if (stat == null) {
System.out.println("/parent 節點不存在,嘗試建立");
//不存在,建立parent
zk.create("/parent", "parentData".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//建立子節點
zk.create("/parent/child", "childData".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("節點 /parent,節點 /parent/child 建立完成");
}
//獲取節點資料
System.out.println("正在獲取節點資料...");
stat = new Stat();
byte[] parentData = zk.getData("/parent", true, stat);
System.out.println("/parent節點資料:" + new String(parentData) + ",節點狀態:" + stat);
List<String> children = zk.getChildren("/parent", true);
System.out.println("/parent節點的孩子節點列表:" + children);
//修改節點資料
System.out.println("準備修改節點資料...");
stat = zk.setData("/parent", "parentData2".getBytes(), stat.getVersion());
//刪除節點
System.out.println("準備刪除節點...");
int parentVersion = stat.getVersion();
stat = zk.exists("/parent/child", true);
zk.delete("/parent/child", stat.getVersion());
zk.delete("/parent", parentVersion);
System.out.println("節點刪除完成!");
}
private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
sb.append("0X");
for (byte bt : bytes) {
sb.append(Integer.toHexString(bt));
}
return sb.toString();
}
}
ZooKeeper ACL(許可權驗證)
ACL即Access Control List,控制節點的訪問許可權。 注意: ZooKeeper的許可權驗證是非遞迴的,父節點的ACL對子節點無效。 getData、setData、delete、getChildren等方法都受ACL影響,只有exist和getAcl方法不受影響。
ACL組成
觀察建構函式:
public ACL(
int perms,
org.apache.zookeeper.data.Id id) {
this.perms=perms;
this.id=id;
}
public Id(
String scheme,
String id) {
this.scheme=scheme;
this.id=id;
}
實際上,ACL由3部分組成: perms 一共有5種許可權,根據位運算確定許可權是否開啟: READ:讀許可權 WRITE:寫許可權 CREATE:建立子節點的許可權 DELETE:刪除子節點的許可權 ADMIN:修改許可權的許可權 schema schema和id是密不可分的,id的含義會根據schema的不同而改變。 內建的schema有以下5種:
- world 此時id固定為anyone,對所有使用者開發許可權
- auth 不使用任何id,表示當前已連線的客戶端都擁有該節點的許可權
- ip 此時id為ip地址,形如 192.186.0.0/16,/後的數字表示取前幾位ip地址用於匹配,只有ip匹配的客戶端擁有相應的許可權
- digest 此時id為username:password的形式,其中password需要經過加密,ZooKeeper提供了 DigestAuthenticationProvider類用於加密
- super 和digest方式類似。 超級使用者,擁有所有節點的許可權,此時id也為username:password。 想要讓超級使用者生效,需要修改,在啟動zookeeper的java命令中新增選項-Dzookeeper.DigestAuthenticationProvider.superDigest=username:password. 可在命令列對密碼進行加密:
然後修改bin/zkServer.sh: 在上述程式碼片段新增選項,重啟ZooKeeper即可生效。 id 與schema對應,不再贅述。
Java程式碼操作ACL
package org.lin.zkp;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Perms;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;
/**
* zookeeper許可權驗證
* @author ljf
*
*/
public class Acl {
public static void main(String[] args) throws Exception {
ZooKeeper zk = createZk();
String auth = DigestAuthenticationProvider.generateDigest("jack:rose");
Stat exists = zk.exists("/sct", false);
zk.addAuthInfo("digest", "jack:rose".getBytes());
if (exists == null) {
String nodePath = zk.create("/sct", null,
Arrays.asList(new ACL(Perms.ALL, new Id("digest", auth))),
CreateMode.PERSISTENT);
System.out.println("建立節點:" + nodePath);
}
byte[] data = zk.getData("/sct", false, null);
System.out.println(data);
ZooKeeper zk2 = createZk();
//沒有許可權丟擲異常
zk2.getData("/sct", false, null);
}
private static ZooKeeper createZk() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
ZooKeeper zk = new ZooKeeper("192.168.142.128:2181", 5000,
new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("default event handler:" + event);
latch.countDown();
}
},
false);
//使用countDownLatch等待連線建立,因為zookeeper建立連線的過程是非同步的,不等待下面的操作可能丟擲異常
latch.await();
System.out.println("連線建立完成");
return zk;
}
}
ZooKeeper應用
ZooKeeper常用於:
- 命名服務
- 配置管理
- 叢集監控
- 構建分散式併發原語 如分散式鎖、分散式FIFO佇列、分散式Barrier等
這是由於ZooKeeper本身特性導致:
- 原子性 ZooKeeper對節點資料,以及節點本身的更新是原子性的
- 一致性 對於多個客戶端,ZooKeeper保證每個客戶端獲取到一致的試圖
- 高效性 ZooKeeper資料儲存在記憶體中,並且每個節點儲存的資料量小
下面提供幾個應用示例,以供參考:
ZooKeeper用於叢集監控
原理
- 叢集監視器ClusterMonitor監聽 /cluster 節點的孩子節點變動事件
- 新加入的機器,建立EPEMERAL型別的子節點 /cluster/ip,此時ClusterMonitor監聽到Child Create事件
- 機器宕機,連線斷開,此時EPHEMERAL節點失效,ClusterMonitor監聽到Child Delete事件 ClusterMonitor
package org.lin.zkp.clt;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
/**
* 叢集監控
* @author ljf
*
*/
public class ClusterMonitor implements Watcher {
private static final String CLUSTER_ROOT = "/cluster";
private ZooKeeper zk;
private CountDownLatch latch = new CountDownLatch(1);
public static void main(String[] args) throws Exception {
new ClusterMonitor().start();
}
private void initZk() throws Exception {
zk = new ZooKeeper("192.168.142.128:2181", 5000, this);
latch.await();
System.out.println("叢集監視器成功連線zookeeper");
}
public void start() throws Exception {
initZk();
Stat exists = zk.exists(CLUSTER_ROOT, false);
if (exists == null) {
zk.create(CLUSTER_ROOT, "clusterRoot".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
List<String> children = zk.getChildren(CLUSTER_ROOT, true);
System.out.println("叢集監視器啟動成功,當前叢集所有節點:" + children);
//阻塞,一直監聽zookeeper訊息
synchronized (this) {
wait();
}
}
@Override
public void process(WatchedEvent event) {
if (event.getState() == KeeperState.SyncConnected && EventType.None == event.getType()) {
latch.countDown();
}
if (event.getType() == EventType.NodeChildrenChanged) {
try {
List<String> children = zk.getChildren(CLUSTER_ROOT, true); //重新註冊watcher
System.out.println(Thread.currentThread().getName() + "叢集變動,當前所有節點:" + children);
} catch (KeeperException | InterruptedException e) {
e.printStackTrace();
System.err.println("獲取叢集節點異常!");
throw new RuntimeException(e);
}
}
}
}
SingleNode
package org.lin.zkp.clt;
import java.lang.management.ManagementFactory;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
/**
* 叢集節點,建立EPHERMAL節點
* @author ljf
*
*/
public class SingleNode {
private static final String CLUSTER_ROOT = "/cluster";
private ZooKeeper zk;
private String processId;
private CountDownLatch latch = new CountDownLatch(1);
相關推薦
Zookeeper入門與實戰
ZooKeeper基本概念
Zookeeper是用於構建分散式系統的協調程式,可用於分散式系統的叢集監控、配置管理、構建分散式鎖等。
Zookeeper完全由Java編寫,客戶端有Java和C版本。
下面介紹ZooKeeper的核心概念。
ZNode
ZooK
xgboost入門與實戰(原理篇)
enc 之前 fine 小結 附近 step 參考 search line http://blog.csdn.net/sb19931201/article/details/52557382
xgboost入門與實戰(原理篇)
前言:
xgboost是大規模並行booste
CK2020微信小程序入門與實戰 常用組件API開發技巧項目實戰
註冊 form 項目 pack filesize 記錄 tps http 謝謝
CK2020微信小程序入門與實戰 常用組件API開發技巧項目實戰
新年伊始,學習要趁早,點滴記錄,學習就是進步!
隨筆背景:在很多時候,很多入門不久的朋友都會問我:我是從其他語言轉到程序開發
Docker入門與實戰講解
pau spa 個人 開發人員 1.0 創建 依賴 之前 講解 簡述
Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後發布到任何流行的 Linux 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任何接口
2018最新python數據分析入門與實戰
.com color tid 實戰 pro nag com forum png
下載地址:百度網盤請添加鏈接描述2018最新python數據分析入門與實戰
移動端App UI 設計入門與實戰
初步了解 tar 1-1 邏輯 -s 形式 流程 建立 實戰 第1章 課程介紹本章為課程導學,幫助同學們初步了解UI設計,介紹實戰課程安排,並熟悉產品設計、開發流程,了解如何與其它崗位配合。1-1 導學視頻1-2 產品開發流程
第2章 產品需求解析本章將針對產品需求進行解析
Python3數據科學入門與實戰
第7章 python 聚合 數學 nac data- notebook 畫圖 das 第1章 實驗環境的搭建 1-1 導學視頻 1-2 Anaconda和Jupyter notebook介紹 1-3 Anaconda在Mac上的安裝演示 1-4 Anacon
微信小遊戲入門與實戰 引爆朋友圈
收獲 第6章 ... 運行 框架搭建 比較 -s 項目 工具 第1章 準備工作(需要ES5,ES6基礎)學員作品演示:https://pan.baidu.com/s/1gEMWzujg72soj0cEUOtJ2A 密碼:uy2n,本章首先介紹課程目標,學習收獲等,然後通過與
單片機入門與實戰
連接 引腳 校驗 設置 部分 模擬 控制 usart 復位
此文參考《PIC單片機入門與實戰》張明鋒編著
此書共十一章,介紹了從單片機的結構和指令系統到使用C語言編寫程序實現對外圍設備的控制。
PIC單片機的結構和指令系統
本章目標
了解市面上的單片機種類
單片機的大
2018年最新Python3資料科學入門與實戰教程
課程簡介: 這是一個數據驅動的時代,想要從事機器學習、人工智慧、資料探勘等前沿技術,都離不開資料跟蹤,本課程通過Numpy、Pandas進行資料科學計算,通過Seaborn、 Matplotlib進行資料圖形化展示;從實戰角度出發,讓你在資料科學領域邁出重要的一步,開啟Data Scien
微控制器入門與實戰
此文參考《PIC微控制器入門與實戰》張明鋒編著
此書共十一章,介紹了從微控制器的結構和指令系統到使用C語言編寫程式實現對外圍裝置的控制。
PIC微控制器的結構和指令系統
本章目標
瞭解市面上的單片機種類
微控制器的大致結構
微控制器如何讀取和執行指令
如何人為的控制微控制器
全網首發 商業級支付寶小程式入門與實戰
第1章 課程導學與準備工作
本章主要介紹為何學習支付寶小程式,以及開發支付寶小程式能為我們帶來哪些收穫。之後會為大家介紹本課程內容具體安排,最後給出如何學好這門課程的一些學習建議。希望大家都能通過這門課程,學有所成,學有所歸。
1-1 課程導學
全網首發 商業級支付寶小程序入門與實戰
課程 質量 文件 綁定 購物 content 排列 warp 自適應
第1章 課程導學與準備工作
本章主要介紹為何學習支付寶小程序,以及開發支付寶小程序能為我們帶來哪些收獲。之後會為大家介紹本課程內容具體安排,最後給出如何學好這門課程的一些學習建議。希望大家都能通過這
微信小程式入門與實戰 常用元件 API 開發技巧 專案實戰
開始就以專案為出發點,不會講一大堆枯燥的語法再補充兩個案例了事,將帶你快速熟悉小程式基礎知識,然後直接進入實戰開發環節,將小程式的知識點貫穿在整個專案中
課程不僅僅講解小程式開發,更會通過實際的編碼來
Python資料探勘入門與實戰:第一章
程式碼來源於:https://github.com/hLvMxM/Learning_Data_Mining_with_Python/blob/master/Chapter 1/ch1_affinity.ipynb 其中註釋是在自己學習中加上去的, 便於初學者看懂 分析文字為:affinity
nginx入門與實戰
參考:https://www.cnblogs.com/pyyu/p/9468680.html
web伺服器軟體
1.一般請求靜態資源是會用到,如圖片,MP4,index頁面
常見的有
IIS (windows底下的web伺服器軟體)
Nginx (Linux底下新一代高效能的
Yii2.0框架入門與實戰專案開發
Yii2框架入門
1.yii框架介紹
2.yii入門
3.yii框架結構解析
4.控制器
5.模型
6.檢視
7.模組
8.部件
9.路由
10.url解析和生成
11.日誌處理
12.錯誤處理
13.元件
14.屬性
15.事件
16.行為
17.服務定位器
Python3資料科學入門與實戰
4-1 DataFrame的簡單數學計算
4-2 Series和DataFrame的排序
4-3 重新命名Dataframe的index
4-4 DataFrame的merge操作
4-5 Concatenate和Combine
4-6 通過apply進行資料預處理
4-7 通過去重進
Docker技術入門與實戰 第8章 使用Dockerfile建立映象
Dockerfile是一個文字格式的配置檔案,使用者可以使用Dockerfile來快速建立自定義映象。本章首先介紹Dockerfile典型的基本結構和它支援的眾多指令,並具體講解通過這些指令來編寫定製映象的Dockerfile,以及如何生成映象。最後介紹使用Dockerfil
Centos 7 Vagrant 簡單入門與實戰介紹
Vagrant 是一個基於 Ruby 的工具,用於建立和部署虛擬化開發環境。它使用 Oracle 的開源 VirtualBox 虛擬化系統,使用 Chef 建立自動化虛擬環境(百度百科)。可以利用 Vagrant 搭建小小的叢集環境,用於學習例如 Ansible