3 Zookeeper實戰

Zookeeper實戰

1.常用的命令

命令基本語法

功能描述

help

顯示所有操作命令

ls path [watch]

使用 ls 命令來查看當前znode中所包含的內容

ls2 path [watch]

查看當前節點數據並能看到更新次數等數據

create

普通創建

-s  含有序列

-e  臨時(重啓或者超時消失)

get path [watch]

獲得節點的值

set

設置節點的具體值

stat

查看節點狀態

delete

刪除節點

rmr

遞歸刪除節點

啓動zk服務

    bin/zkServer.sh start

啓動客戶端

   bin/zkCli.sh

查看zk的運行狀態

    bin/zkServer.sh status

help 查看客戶端幫助命令

    help

 

查看當前znode中所包含的內容

    ls /

 

查看當前節點詳細數據

   ls2 /

get 獲取節點數據和更新信息

    get內容爲空
    cZxid :創建節點的id
    ctime : 節點的創建時間
    mZxid :修改節點的id
    mtime :修改節點的時間
    pZxid :子節點的id
    cversion : 子節點的版本
    dataVersion : 當前節點數據的版本
    aclVersion :權限的版本
    ephemeralOwner :判斷是否是臨時節點
    dataLength : 數據的長度
    numChildren :子節點的數量

stat 獲得節點的更新信息

    stat  path

create 創建節點

    create [-s] [-e] path data acl 可以注意一下各個版本的變化


create -e 創建臨時節點

    create -e  path  data

create -s 創建順序節點 自動累加

    create -s  path data

 

修改節點

     set path data [version]

刪除節點

    delete path [version]

遞歸刪除節點

    rmr path

關於watcher機制大體的理解可以爲,當每個節點發生變化,都會觸發watcher事件,類似於mysql的觸發器。zk中 watcher是一次性的,觸發後立即銷燬。

節點的值變化監聽
      stat path [watch] 設置watch事件
      get path [watch]設置watch事件

節點的子節點變化監聽(路徑變化)

     ls path watch

 當路徑發生變化

2.集羣部署

部署前的準備工作

      保證各個主機之間能夠正常通信,最好是在同一網段,開放要使用的端口或者關閉防火牆。

    修改host文件,加入IP和主機名的映射。方法爲修改/etc/hosts和etc/hostname文件,不同的Linux發行版方法不一定一樣。

 

訪問官網下載Zookeeper安裝包,並解壓。

tar -xvzf zookeeper-3.4.10.tar.gz

創建數據目錄

     執行以下命令創建數據目錄:       

mkdir /usr/zookeeper/data

     執行以下命令創建日誌目錄:

  mkdir /usr/zookeeper/data/log

      執行以下命令創建myid文件,並寫入ID: 

 echo 1 > /usr/zookeeper/data/myid

    修改配置

        執行以下命令編輯zoo.cfg文件:   

cd zookeeper-3.4.10/conf/ && mv zoo_sample.cfg zoo.cfg && vi zoo.cfg  

  修改配置如下:

dataDir=/usr/zookeeper/data

dataLogDir=/usr/zookeeper/data/log

autopurge.snapRetainCount=3

autopurge.purgeInterval=1

  在最後添加Zookeeper集羣各節點地址:

server.1=node1:2888:3888

server.2=node2:2888:3888

server.3=node3:2888:3888

配置參數解讀

server.A=B:C:D

A是一個數字,表示這個是第幾號服務器;

集羣模式下配置一個文件myid,這個文件在dataDir目錄下,這個文件裏面有一個數據就是A的值,Zookeeper啓動時讀取此文件,拿到裏面的數據與zoo.cfg裏面的配置信息比較從而判斷到底是哪個server

B是這個服務器的ip地址;

C是這個服務器與集羣中的Leader服務器交換信息的端口;

D是萬一集羣中的Leader服務器掛了,需要一個端口來重新進行選舉,選出一個新的Leader,而這個端口就是用來執行選舉時服務器相互通信的端口。

拷貝配置文件到其他節點

scp -r zookeeper-3.4.10/ node2:/usr/

  這裏需要注意的是,每個節點中的myid是不能相同的。

      

3.代碼中應用

 

   創建maven工程,添加依賴

<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.8.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
		<dependency>
			<groupId>org.apache.zookeeper</groupId>
			<artifactId>zookeeper</artifactId>
			<version>3.4.10</version>
		</dependency>
</dependencies>

客戶端代碼

private static String connectString =
 "host1:2181,host2:2181,host3:2181";
	private static int sessionTimeout = 2000;
	private ZooKeeper zkClient = null;
	@Before
	public void init() throws Exception {
	zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
			@Override
			public void process(WatchedEvent event) {

				// 收到事件通知後的回調函數(用戶的業務邏輯)
				System.out.println(event.getType() + "--" + event.getPath());

				// 再次啓動監聽
				try {
					zkClient.getChildren("/", true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

 

創建子節點

@Test
public void create() throws Exception {

		// 參數1:要創建的節點的路徑; 參數2:節點數據 ; 參數3:節點權限 ;參數4:節點的類型
		String nodeCreated = zkClient.create("/atguigu", "jinlian".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}

獲取子節點並監聽節點變化

@Test
public void getChildren() throws Exception {
		List<String> children = zkClient.getChildren("/", true);
		for (String child : children) {
			System.out.println(child);
		}
		// 延時阻塞
		Thread.sleep(Long.MAX_VALUE);
}

判斷Znode是否存在

@Test
public void exist() throws Exception {
	Stat stat = zkClient.exists("/eclipse", false);
	System.out.println(stat == null ? "not exist" : "exist");
}

監聽服務器節點動態上下線案例

先在集羣上創建/servers節點  create /servers "servers"

服務器端向Zookeeper註冊代碼

public class DistributeServer {
	private static String connectString = "host1:2181,host2:2181,host3:2181";
	private static int sessionTimeout = 2000;
	private ZooKeeper zk = null;
	private String parentNode = "/servers";
	// 創建到zk的客戶端連接
	public void getConnect() throws IOException{
		zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
			@Override
			public void process(WatchedEvent event) {

			}
		});
	}
	
	// 註冊服務器
	public void registServer(String hostname) throws Exception{

		String create = zk.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);	
		System.out.println(hostname +" is online "+ create);
	}
	
	// 業務功能
	public void business(String hostname) throws Exception{
		System.out.println(hostname+" is working ...");	
		Thread.sleep(Long.MAX_VALUE);
	}
	
	public static void main(String[] args) throws Exception {
		
// 1獲取zk連接
		DistributeServer server = new DistributeServer();
		server.getConnect();	
		// 2 利用zk連接註冊服務器信息
		server.registServer(args[0]);		
		// 3 啓動業務功能
		server.business(args[0]);
	}
}

客戶端代碼

public class DistributeClient {

	private static String connectString = "host1:2181,host2:2181,host3:2181";
	private static int sessionTimeout = 2000;
	private ZooKeeper zk = null;
	private String parentNode = "/servers";
	// 創建到zk的客戶端連接
	public void getConnect() throws IOException {
		zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
			@Override
			public void process(WatchedEvent event) {
				// 再次啓動監聽
				try {
					getServerList();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	// 獲取服務器列表信息
	public void getServerList() throws Exception {
		
		// 1獲取服務器子節點信息,並且對父節點進行監聽
		List<String> children = zk.getChildren(parentNode, true);

        // 2存儲服務器信息列表
		ArrayList<String> servers = new ArrayList<>();
		
        // 3遍歷所有節點,獲取節點中的主機名稱信息
		for (String child : children) {
			byte[] data = zk.getData(parentNode + "/" + child, false, null);
			servers.add(new String(data));
		}

        // 4打印服務器列表信息
		System.out.println(servers);
	}
	// 業務功能
	public void business() throws Exception{
	       System.out.println("client is working ...");
Thread.sleep(Long.MAX_VALUE);
	}

	public static void main(String[] args) throws Exception {
		// 1獲取zk連接
		DistributeClient client = new DistributeClient();
		client.getConnect();
		// 2獲取servers的子節點信息,從中獲取服務器信息列表
		client.getServerList();
		// 3業務進程啓動
		client.business();
	}
}

 

 

 

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