1. 程式人生 > >Zookeeper入門與實戰

Zookeeper入門與實戰

ZooKeeper基本概念

Zookeeper是用於構建分散式系統協調程式,可用於分散式系統的叢集監控、配置管理、構建分散式鎖等。 Zookeeper完全由Java編寫,客戶端有Java和C版本。 下面介紹ZooKeeper的核心概念。

ZNode

ZooKeeper類似一個遠端檔案系統,根節點為"/"。這個檔案系統由稱為znode的節點組成,每個znode包含pathdataZookeeper資料模型 有4種類型的znode:

  • EPHEMERAL 臨時節點,在session期間有效,因此臨時節點無法建立孩子節點。
  • EPHEMERAL_SEQUENTIAL 臨時序列節點,會在末尾新增序號,格式為%010,從1,位數不足10位在前面補0,最小的序號由父節點保持。
  • PERSISTENT 永久節點,將序列化到Zookeeper伺服器
  • PERSISTENT_SEQUENTIAL 永久序列節點

Watcher

watcher是監聽器的意思,zookeeper客戶端可以對znode設定Watcher,當znode狀態變化時,zookeeper伺服器會對設定了Watcher的客戶端傳送通知。

ZooKeeper ClientZooKeeper Service設定Watcher到znode通知znode變動事件ZooKeeper ClientZooKeeper Service

ZooKeeper安裝

執行環境

  • Linux系統
  • Java執行環境

安裝步驟

  1. 解壓zookeeper-3.4.13.tar.gz
    到安裝目錄 mv到希望安裝的目錄,解壓命令 **tar -zxvf <壓縮檔案>**解壓即可。 解壓完成後,如下圖所示: 在這裡插入圖片描述
  2. 配置檔案 conf目錄下存放了zookeeper相關的配置檔案: 在這裡插入圖片描述 初始的時候,zoo.cfg檔案不存在,只存在模板檔案zoo_sample.cfg。 通過mv或cp命令,得到zoo.cfg,編輯檔案內容如下: 在這裡插入圖片描述 zookeeper實際上支援叢集配置,初始情況下我們配置單機版。 重要的配置項: dataDir:zookeeper資料存放的資料夾,需要預先建立 clientPort:zookeeper服務埠,客戶端通過該埠與zookeeper通訊 此外,log4j.properties
    為zookeeper日誌配置檔案,參考log4j配置即可。
  3. 啟動ZooKeeper 命令列執行 bin/zkServer.sh start,啟動ZooKeeper服務。 在這裡插入圖片描述

至此,ZooKeeper單機部署完成。

bin/zkCli.sh 是zookeeper內建的客戶端,可通過命令列操作zookeeper。

  1. 啟動客戶端 zookeeper根目錄下,命令列輸入 bin/zkCli.sh啟動客戶端。 在這裡插入圖片描述
  2. 客戶端命令簡介
命令 作用
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用於叢集監控

原理

  1. 叢集監視器ClusterMonitor監聽 /cluster 節點的孩子節點變動事件
  2. 新加入的機器,建立EPEMERAL型別的子節點 /cluster/ip,此時ClusterMonitor監聽到Child Create事件
  3. 機器宕機,連線斷開,此時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