天天看點

大資料技術之Zookeeper 第4章 Zookeeper實戰

4.1 分布式安裝部署

0)叢集規劃

在hadoop102、hadoop103和hadoop104三個節點上部署Zookeeper。

1)解壓安裝

(1)解壓zookeeper安裝包到/opt/module/目錄下

[[email protected] software]$ tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/

(2)在/opt/module/zookeeper-3.4.10/這個目錄下建立zkData

mkdir -p zkData

(3)重命名/opt/module/zookeeper-3.4.10/conf這個目錄下的zoo_sample.cfg為zoo.cfg

mv zoo_sample.cfg zoo.cfg

2)配置zoo.cfg檔案

(1)具體配置

dataDir=/opt/module/zookeeper-3.4.10/zkData

增加如下配置

#######################cluster##########################

server.2=hadoop102:2888:3888

server.3=hadoop103:2888:3888

server.4=hadoop104:2888:3888

(2)配置參數解讀

Server.A=B:C:D。

A是一個數字,表示這個是第幾号伺服器;

B是這個伺服器的ip位址;

C是這個伺服器與叢集中的Leader伺服器交換資訊的端口;

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

叢集模式下配置一個檔案myid,這個檔案在dataDir目錄下,這個檔案裡面有一個資料就是A的值,Zookeeper啟動時讀取此檔案,拿到裡面的資料與zoo.cfg裡面的配置資訊比較進而判斷到底是哪個server。

3)叢集操作

(1)在/opt/module/zookeeper-3.4.10/zkData目錄下建立一個myid的檔案

touch myid

添加myid檔案,注意一定要在linux裡面建立,在notepad++裡面很可能亂碼

(2)編輯myid檔案

vi myid

在檔案中添加與server對應的編号:如2

(3)拷貝配置好的zookeeper到其他機器上

scp -r zookeeper-3.4.10/ [email protected]:/opt/app/

scp -r zookeeper-3.4.10/ [email protected]:/opt/app/

并分别修改myid檔案中内容為3、4

(4)分别啟動zookeeper

[[email protected] zookeeper-3.4.10]# bin/zkServer.sh start

[[email protected] zookeeper-3.4.10]# bin/zkServer.sh start

[[email protected] zookeeper-3.4.10]# bin/zkServer.sh start

(5)檢視狀态

[[email protected] zookeeper-3.4.10]# bin/zkServer.sh status

JMX enabled by default

Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg

Mode: follower

[[email protected] zookeeper-3.4.10]# bin/zkServer.sh status

JMX enabled by default

Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg

Mode: leader

[[email protected] zookeeper-3.4.5]# bin/zkServer.sh status

JMX enabled by default

Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg

Mode: follower

4.2 用戶端指令行操作

指令基本文法 功能描述
help 顯示所有操作指令
ls path [watch] 使用 ls 指令來檢視目前znode中所包含的内容
ls2 path [watch] 檢視目前節點資料并能看到更新次數等資料
create

普通建立

-s  含有序列

-e  臨時(重新開機或者逾時消失)

get path [watch] 獲得節點的值
set 設定節點的具體值
stat 檢視節點狀态
delete 删除節點
rmr 遞歸删除節點

1)啟動用戶端

[[email protected] zookeeper-3.4.10]$ bin/zkCli.sh

2)顯示所有操作指令

[zk: localhost:2181(CONNECTED) 1] help

3)檢視目前znode中所包含的内容

[zk: localhost:2181(CONNECTED) 0] ls /

[zookeeper]

4)檢視目前節點資料并能看到更新次數等資料

[zk: localhost:2181(CONNECTED) 1] ls2 /

[zookeeper]

cZxid = 0x0

ctime = Thu Jan 01 08:00:00 CST 1970

mZxid = 0x0

mtime = Thu Jan 01 08:00:00 CST 1970

pZxid = 0x0

cversion = -1

dataVersion = 0

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 0

numChildren = 1

5)建立普通節點

[zk: localhost:2181(CONNECTED) 2] create /app1 "hello app1"

Created /app1

[zk: localhost:2181(CONNECTED) 4] create /app1/server101 "192.168.1.101"

Created /app1/server101

6)獲得節點的值

[zk: localhost:2181(CONNECTED) 6] get /app1

hello app1

cZxid = 0x20000000a

ctime = Mon Jul 17 16:08:35 CST 2017

mZxid = 0x20000000a

mtime = Mon Jul 17 16:08:35 CST 2017

pZxid = 0x20000000b

cversion = 1

dataVersion = 0

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 10

numChildren = 1

[zk: localhost:2181(CONNECTED) 8] get /app1/server101

192.168.1.101

cZxid = 0x20000000b

ctime = Mon Jul 17 16:11:04 CST 2017

mZxid = 0x20000000b

mtime = Mon Jul 17 16:11:04 CST 2017

pZxid = 0x20000000b

cversion = 0

dataVersion = 0

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 13

numChildren = 0

7)建立短暫節點

[zk: localhost:2181(CONNECTED) 9] create -e /app-emphemeral 8888

(1)在目前用戶端是能檢視到的

[zk: localhost:2181(CONNECTED) 10] ls /

[app1, app-emphemeral, zookeeper]

(2)退出目前用戶端然後再重新開機用戶端

[zk: localhost:2181(CONNECTED) 12] quit

[[email protected] zookeeper-3.4.10]$ bin/zkCli.sh

(3)再次檢視根目錄下短暫節點已經删除

[zk: localhost:2181(CONNECTED) 0] ls /

[app1, zookeeper]

8)建立帶序号的節點

(1)先建立一個普通的根節點app2

[zk: localhost:2181(CONNECTED) 11] create /app2 "app2"

(2)建立帶序号的節點

[zk: localhost:2181(CONNECTED) 13] create -s /app2/aa 888

Created /app2/aa0000000000

[zk: localhost:2181(CONNECTED) 14] create -s /app2/bb 888

Created /app2/bb0000000001

[zk: localhost:2181(CONNECTED) 15] create -s /app2/cc 888

Created /app2/cc0000000002

如果原節點下有1個節點,則再排序時從1開始,以此類推。

[zk: localhost:2181(CONNECTED) 16] create -s /app1/aa 888

Created /app1/aa0000000001

9)修改節點資料值

[zk: localhost:2181(CONNECTED) 2] set /app1 999

10)節點的值變化監聽

(1)在104主機上注冊監聽/app1節點資料變化

[zk: localhost:2181(CONNECTED) 26] get /app1 watch

(2)在103主機上修改/app1節點的資料

[zk: localhost:2181(CONNECTED) 5] set /app1  777

(3)觀察104主機收到資料變化的監聽

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/app1

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

(1)在104主機上注冊監聽/app1節點的子節點變化

[zk: localhost:2181(CONNECTED) 1] ls /app1 watch

[aa0000000001, server101]

(2)在103主機/app1節點上建立子節點

[zk: localhost:2181(CONNECTED) 6] create /app1/bb 666

Created /app1/bb

(3)觀察104主機收到子節點變化的監聽

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/app1

12)删除節點

[zk: localhost:2181(CONNECTED) 4] delete /app1/bb

13)遞歸删除節點

[zk: localhost:2181(CONNECTED) 7] rmr /app2

14)檢視節點狀态

[zk: localhost:2181(CONNECTED) 12] stat /app1

cZxid = 0x20000000a

ctime = Mon Jul 17 16:08:35 CST 2017

mZxid = 0x200000018

mtime = Mon Jul 17 16:54:38 CST 2017

pZxid = 0x20000001c

cversion = 4

dataVersion = 2

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 3

numChildren = 2

4.3 API應用

4.3.1 eclipse環境搭建

1)建立一個Maven工程

2)添加pom檔案

<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>

3)拷貝log4j.properties檔案到項目根目錄

https://share.weiyun.com/56Zlk86

4.3.2 建立ZooKeeper用戶端

private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104: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();

}

}

});

}

4.3.3 建立子節點

// 建立子節點

@Test

public void create() throws Exception {

// 資料的增删改查

// 參數1:要建立的節點的路徑; 參數2:節點資料 ; 參數3:節點權限 ;參數4:節點的類型

String nodeCreated = zkClient.create("/eclipse", "hello zk".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);

}

4.3.4 擷取子節點并監聽

// 擷取子節點

@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);

}

4.3.5 判斷znode是否存在

// 判斷znode是否存在

@Test

public void exist() throws Exception {

Stat stat = zkClient.exists("/eclipse", false);

System.out.println(stat == null ? "not exist" : "exist");

}

4.4 案例實戰

監聽伺服器節點動态上下線案例

1)需求:某分布式系統中,主節點可以有多台,可以動态上下線,任意一台用戶端都能實時感覺到主節點伺服器的上下線

2)需求分析

大資料技術之Zookeeper 第4章 Zookeeper實戰

3)具體實作:

(0)現在叢集上建立/servers節點

[zk: localhost:2181(CONNECTED) 10] create /servers "servers"

Created /servers

(1)伺服器端代碼

package com.atguigu.zkcase;

import java.io.IOException;

import org.apache.zookeeper.CreateMode;

import org.apache.zookeeper.WatchedEvent;

import org.apache.zookeeper.Watcher;

import org.apache.zookeeper.ZooKeeper;

import org.apache.zookeeper.ZooDefs.Ids;

public class DistributeServer {

private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104: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 noline "+ 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 {

// 擷取zk連接配接

DistributeServer server = new DistributeServer();

server.getConnect();

// 利用zk連接配接注冊伺服器資訊

server.registServer(args[0]);

// 啟動業務功能

server.business(args[0]);

}

}

(2)用戶端代碼

package com.atguigu.zkcase;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

import org.apache.zookeeper.WatchedEvent;

import org.apache.zookeeper.Watcher;

import org.apache.zookeeper.ZooKeeper;

public class DistributeClient {

private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";

private static int sessionTimeout = 2000;

private ZooKeeper zk = null;

private String parentNode = "/servers";

private volatile ArrayList<String> serversList = new ArrayList<>();

// 建立到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 {

// 擷取伺服器子節點資訊,并且對父節點進行監聽

List<String> children = zk.getChildren(parentNode, true);

ArrayList<String> servers = new ArrayList<>();

for (String child : children) {

byte[] data = zk.getData(parentNode + "/" + child, false, null);

servers.add(new String(data));

}

// 把servers指派給成員serverList,已提供給各業務線程使用

serversList = servers;

System.out.println(serversList);

}

// 業務功能

public void business() throws Exception {

System.out.println("client is working ...");

Thread.sleep(Long.MAX_VALUE);

}

public static void main(String[] args) throws Exception {

// 擷取zk連接配接

DistributeClient client = new DistributeClient();

client.getConnect();

// 擷取servers的子節點資訊,從中擷取伺服器資訊清單

client.getServerList();

// 業務程序啟動

client.business();

}

}

本教程由尚矽谷教育大資料研究院出品,如需轉載請注明來源。