Zookeeper基礎入門與安裝部署

【1】Zookeeper基礎入門

① Zookeeper是什麼

Zookeeper是一個開源的分佈式的、爲分佈式應用提供協調服務的Apache項目。

Zookeeper從設計模式角度來理解,其實是一個基於觀察者模式設計的分佈式服務管理框架。它負責存儲和管理大家都關心的數據,然後接受觀察者的註冊。一旦這些數據的狀態發送變化,Zookeeper就將負責通知已經在Zookeeper上註冊的那些觀察者做出相應的反應。從Zookeeper存儲數據和通知機制來講,可以說Zookeeper=文件系統+通知機制。

zookeeper實現服務器節點動態上下線過程描述如下:

  • 服務端啓動時去註冊信息(創建的都是臨時節點);
  • 客戶端獲取到當前在線服務器列表,並且註冊監聽;
  • 服務器節點下線;
  • 服務器節點上下線事件通知(Zookeeper負責);
  • 客戶端收到監聽通知則做出相應反應,比如重新獲取在線服務器列表註冊監聽。

② Zookeeper集羣特點

集羣如下圖所示:
在這裏插入圖片描述

  • Zookeeper集羣是一個leader和多個follow組成的集羣。
  • 集羣中只要半數以上節點存活,Zookeeper集羣就能正常服務。
  • 全局數據一致,每個server保存一份相同的數據副本,client無論連接到哪個server,數據都是一致的。
  • 更新請求順序進行,來自同一個Client的更新請求按其發送順序依次執行。
  • 數據更新原子性,一次數據更新要麼成功,要麼失敗。
  • 實時性,在一定時間範圍內,Client能讀到最新數據。

③ Zookeeper的數據結構

Zookeeper的數據模型的結構與UNIX文件系統很類似,整體上可以看做是一棵樹,每個節點稱做一個ZNode。每一個ZNode默認能夠存儲1MB的數據,每個ZNode可以通過其路徑唯一標識。

如下圖所示:
在這裏插入圖片描述


④ 應用場景

Zookeeper有諸多應用場景,如統一命名服務、統一配置管理、統一集羣管理、服務器節點動態上下線、軟負載均衡等。

  • 統一命名服務

在分佈式環境下,經常需要對應用/服務進行統一命名,便於區別。例如IP不容易記住而域名容易記住。

在這裏插入圖片描述

  • 統一配置管理

分佈式環境下,配置文件同步非常常見。一般要求一個集羣中,所有節點的配置信息是一致的,比如kafka集羣。對配置文件修改後,希望能夠快速同步到各個節點上。

配置管理可交由Zookeeper實現:可將配置信息寫入Zookeeper上的一個ZNode;每個客戶端服務器監聽這個ZNode;一旦ZNode中的數據被修改,Zookeeper將通知各個客戶端。

在這裏插入圖片描述


  • 統一集羣管理

分佈式環境中,實時掌握每個節點的狀態是很必要的,以便可以根據節點實時狀態做出一些調整。

Zookeeper可以實現實時監控節點狀態的變化:可以將節點信息寫入Zookeeper的一個ZNode;監聽這個ZNode可獲取它的實時狀態變化。

在這裏插入圖片描述


  • 軟負載均衡

在Zookeeper中記錄每臺服務器的訪問數,讓訪問數最少的服務器去處理最新的客戶端請求。


【2】單擊版Zookeeper下載與安裝

官網地址:http://zookeeper.apache.org/

在這裏插入圖片描述

下載地址:https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/
在這裏插入圖片描述


① 本機模式安裝Zookeeper

這裏下載的是3.5.5版本,將其放到linux某個路徑下(這裏有個坑,請下載apache-zookeeper-3.5.5-bin.tar.gz,該包可以正常使用。apache-zookeeper-3.5.5.tar.gz是源碼包):
在這裏插入圖片描述
注意,安裝Zookeeper一定先安裝好jdk,linux安裝jdk可以參考如下博文:
Linux下源碼安裝jdk1.8CentOS7 下rpm安裝jdk1.8

安裝步驟如下:

  • 解壓
tar -zxvf apache-zookeeper-3.5.5-bin.tar.gz
 //或者指定解壓目錄
 tar -zxvf apache-zookeeper-3.5.5-bin.tar.gz -C /home/softinstall
  • 修改配置文件(把conf中的zoo_sample.cfg重命名爲zoo.cfg)
cd  apache-zookeeper-3.5.5/conf
mv zoo_sample.cfg zoo.cfg
//配置數據路徑
mkdir -p /home/softinstall/apache-zookeeper-3.5.5/zkData
vim zoo.cfg

在這裏插入圖片描述


② 操作Zookeeper

  • 啓動Zookeeper服務端
[root@localhost apache-zookeeper-3.5.5-bin]# bin/zkServer.sh  start
ZooKeeper JMX enabled by default
Using config: /opt/softinstall/apache-zookeeper-3.5.5-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

[root@localhost apache-zookeeper-3.5.5-bin]# jps
27368 QuorumPeerMain
27388 Jps
  • 關閉zkserver
 bin/zkServer.sh  stop
  • 查看服務狀態
[root@localhost apache-zookeeper-3.5.5-bin]# bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/softinstall/apache-zookeeper-3.5.5-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: standalone    //表示單機模式
  • 重啓Zookeeper服務
//進入目錄下
 bin/zkServer.sh restart
  • 啓動客戶端
 bin/zkCli.sh

在這裏插入圖片描述

  • 查看根目錄下內容
[zk: localhost:2181(CONNECTED) 2] ls /
[zookeeper]
  • 退出客戶端
[zk: localhost:2181(CONNECTED) 6] quit

【3】Zookeeper配置文件參數解讀

配置文件主要參數如下:

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/home/softinstall/apache-zookeeper-3.5.5/zkData
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1

① tickTime=2000

該參數含義爲通信心跳數 ,Zookeeper服務器端和客戶端心跳時間,單位毫秒。2000表示2S一次心跳檢測,也就是每個tickTime時間就會發送一個心跳。它用於心跳機制,並且設置最小的session超時時間爲兩倍心跳時間(session的最小超時時間=2*tickTime)。

② initLimit=10

集羣中的follower與leader之間初始連接時能容忍的最多心跳數(tickTime的數量),用它來限定集羣中Zookeeper服務器連接到leader的時限。

10個心跳幀,10*2=20s是最開始通信時leader和follower最大延時時間。如果超過該時間,則認爲二者斷開通信。

③ syncLimit=5

集羣正常啓動後集羣中leader與follower之間的最大響應時間單位。假如響應時間超過syncLimit*tickTime,leader認爲follower死掉,從服務器列表中刪除follower。

④ clientPort=2181

客戶端與服務端通信的端口號,默認爲2181。

⑤ dataDir

zookeeper的數據目錄。另外還有日誌文件目錄默認在../apache-zookeeper-3.5.5-bin/logs下。


【3】利用zookeeper監聽服務器動態上下線實例

背景需求如下:某分佈式系統中,主節點有多臺,可能進行動態上下線,任意一臺客戶端都能實時感知到主節點服務器的上下線狀態。

客戶端代碼

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

public class DistributeClient {

	public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
		
		DistributeClient client = new DistributeClient();
		
		// 1 獲取zookeeper集羣連接
		client.getConnect();
		
		// 2 註冊監聽
		client.getChlidren();
		
		// 3 業務邏輯處理
		client.business();
		
	}

	private void business() throws InterruptedException {
		Thread.sleep(Long.MAX_VALUE);
	}

	private void getChlidren() throws KeeperException, InterruptedException {
		
		List<String> children = zkClient.getChildren("/servers", true);
		
		// 存儲服務器節點主機名稱集合
		ArrayList<String> hosts = new ArrayList<String>();
		
		for (String child : children) {
			
			byte[] data = zkClient.getData("/servers/"+child, false, null);
			
			hosts.add(new String(data));
		}
		
		// 將所有在線主機名稱打印到控制檯
		System.out.println(hosts);
		
	}

	private String connectString="127.0.0.1:3181,127.0.0.1:3182,127.0.0.1:3183";
	private int sessionTimeout = 2000;
	private ZooKeeper zkClient;

	private void getConnect() throws IOException {
	
		zkClient = new ZooKeeper(connectString , sessionTimeout , new Watcher() {
			
			public void process(WatchedEvent event) {
				
				try {
					getChlidren();
				} catch (KeeperException e) {
					e.printStackTrace();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
		
	}
}

服務端代碼

import java.io.IOException;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;

public class DistributeServer {

	public static void main(String[] args) throws Exception {
		
		DistributeServer server = new DistributeServer();
		
		// 1 連接zookeeper集羣
		server.getConnect();
		
		// 2 註冊節點
		server.regist(args[0]);
		
		// 3 業務邏輯處理
		server.business();
	}

	private void business() throws InterruptedException {
	
		Thread.sleep(Long.MAX_VALUE);
	}

	private void regist(String hostname) throws KeeperException, InterruptedException {
		//注意,創建的是臨時、有序號節點。這樣服務器down了節點也就不存在了
		String path = zkClient.create("/servers/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
		
		System.out.println(hostname +"is online ");
		
	}

	private String connectString="127.0.0.1:3181,127.0.0.1:3182,127.0.0.1:3183";
	private int sessionTimeout = 2000;
	private ZooKeeper zkClient;

	private void getConnect() throws IOException {
		
		zkClient = new ZooKeeper(connectString , sessionTimeout , new Watcher() {
			
			public void process(WatchedEvent event) {
				// TODO Auto-generated method stub
				
			}
		});
	}
}

zookeeper更多使用參考博文:ZooKeeper學習之內部原理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章