Zookeeper簡介

Floatingshen發表於2020-12-10

一、Zookeeper簡介

1、zookeeper簡介
動物管理員
Apache ZooKeeper致力於開發和維護開源伺服器,實現高度可靠的分散式協調。
2、什麼是ZooKeeper?
ZooKeeper是一種集中式服務,用於維護配置資訊,命名,提供分散式同步和提供組服務。所有這
些型別的服務都以分散式應用程式的某種形式使用。每次實施它們都需要做很多工作來修復不可避
免的錯誤和競爭條件。由於難以實現這些型別的服務,應用程式最初通常會吝嗇它們,這使得它們
在變化的情況下變得脆弱並且難以管理。即使正確完成,這些服務的不同實現也會在部署應用程式
時導致管理複雜性。
3、zookeeper功能
(1)儲存資料
(2)監聽
4、zookeeper工作機制
基於觀察者模式設計的分散式服務管理框架
5、zookeeper的儲存結構
目錄樹結構
6、zookeeper應用場景
(1)叢集統一配置管理
(2)叢集統一命名服務
(3)叢集統一管理
(4)伺服器的動態上下線感知
(5)負載均衡
7、安裝zookeeper單機版
(1)下載安裝包 zookeeper-3.4.10.tar.gz
(2)上傳安裝包到Linux
alt+p(SecureCRT中)
(3)解壓
tar -zxvf zookeeper-3.4.10.tar.gz
(4)修改配置檔案
進入zookeeper安裝目錄下的conf資料夾下
mv zoo_sample.cfg zoo.cfg
vi zoo.cfg
dataDir=/root/hd/zookeeper-3.4.10/zkData
(5)啟動zk
bin/zkServer.sh start
(6)檢視狀態
bin/zkServer.sh status
(7)啟動客戶端
bin/zkCli.sh
8、完全分散式安裝
(1)下載安裝包 zookeeper-3.4.10.tar.gz
(2)上傳安裝包到Linux
alt+p(SecureCRT中)
(3)解壓
tar -zxvf zookeeper-3.4.10.tar.gz
(4)修改配置檔案
進入zookeeper安裝目錄下的conf資料夾下
mv zoo_sample.cfg zoo.cfg
vi zoo.cfg
dataDir=/root/hd/zookeeper-3.4.10/zkData
###############cluster###############
server.1=hd09-1:2888:3888
server.2=hd09-2:2888:3888
server.3=hd09-3:2888:3888
其中server.後面的數字1、2、3分別是機器hd09-1、hd09-2、hd09-3中zookeeper-3.4.10/zkData/myid檔案中的值
(5)新增檔案myid
$cd zookeeper-3.4.10/zkData
$touch myid
(6)新增內容在myid為1
$ vi myid
1
(7)傳送zookeeper檔案到其它機器
$ scp -r zookeeper-3.4.10 hd09-2:$PWD
$ scp -r zookeeper-3.4.10 hd09-3: P W D ( 8 ) 修 改 m y i d 依 次 為 23 ( 9 ) 修 改 環 境 變 量 v i / e t c / p r o f i l e e x p o r t Z O O K E E P E R H O M E = / r o o t / h d / z o o k e e p e r 3.4.10 e x p o r t P A T H = PWD (8)修改myid依次為2 3 (9)修改環境變數 vi /etc/profile export ZOOKEEPER_HOME=/root/hd/zookeeper3.4.10 export PATH= PWD8myid239vi/etc/profileexportZOOKEEPERHOME=/root/hd/zookeeper3.4.10exportPATH=PATH:$ZOOKEEPER_HOME/bin
(10)生效環境變數
source /etc/profile
(11)啟動zookeeper
zkServer.sh start
(12)檢視狀態
zkServer.sh status
(13)關閉zookeeper
zkServer.sh stop

9、客戶端的命令列操作
(1)啟動客戶端
zkCli.sh
(2)檢視幫助
help
(3)檢視當前znode所包含的內容
ls /
(4)建立節點
create /hello 18
(5)建立短暫znode
create -e /haha tom
(6)建立帶序號znode
create -s /bigdata tom
(7)建立短暫帶序號
create -e -s /bigdata tom
(8)檢視此節點的詳細資訊
ls2 /
(9)獲得節點值監聽
get /hello watch
(10)監聽路徑
ls / watch
(11)修改znode資料
set /hello iiiii
(12)刪除節點
delete /hello
(13)遞迴刪除
rmr /delireba
(14)檢視節點狀態資訊
stat /

二、Zookeeper工作機制

1、Zookeeper工作機制
在這裡插入圖片描述

2、Zookeeper目錄結構
在這裡插入圖片描述

3、Zookeeper選舉機制
在這裡插入圖片描述

三、Zookeeper簡單客戶端API

package com.css.zk;

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

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
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;
import org.junit.Before;
import org.junit.Test;

public class ZkClient {

private String connectString = "192.168.146.132:2181,192.168.146.133:2181,192.168.146.134:2181";
private int sessionTimeout = 3000;
ZooKeeper zkCli = null;

// 初始化客戶端
@Before
public void init() throws IOException {
    zkCli = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
        // 回撥監聽
        @Override
        public void process(WatchedEvent event) {
            // System.out.println(event.getPath() + "\t" + event.getState() + "\t" + event.getType());
            try {
                List<String> children = zkCli.getChildren("/", true);
                for (String c : children) {
                    // System.out.println(c);
                }
            } catch (KeeperException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
}

// 建立子節點
@Test
public void createZnode() throws KeeperException, InterruptedException {
    String path = zkCli.create("/hello", "world".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    System.out.println(path);
}

// 獲取子節點
@Test
public void getChild() throws KeeperException, InterruptedException {
    List<String> children = zkCli.getChildren("/", true);
    for (String c : children) {
        System.out.println(c);
    }
    Thread.sleep(Long.MAX_VALUE);
}

// 刪除節點
@Test
public void rmChildData() throws KeeperException, InterruptedException {
    // byte[] data = zkCli.getData("/bbq", true, null);
    // System.out.println(new String(data));
    zkCli.delete("/hello", -1);
}

// 修改資料
@Test
public void setData() throws KeeperException, InterruptedException {
    zkCli.setData("/hello", "17".getBytes(), -1);
}

// 判斷節點是否存在
@Test
public void testExist() throws KeeperException, InterruptedException {
    Stat exists = zkCli.exists("/hello", false);
    System.out.println(exists == null ? "not exists" : "exists");
}

}

四、Zoopeeper監聽API

1、監聽單節點內容

package com.css.zk;

import java.io.IOException;

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

// 監聽單節點內容
public class WatchDemo {
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
ZooKeeper zkCli = new ZooKeeper(“192.168.146.132:2181,192.168.146.133:2181,192.168.146.134:2181”, 3000,
new Watcher() {
// 監聽回撥
@Override
public void process(WatchedEvent event) {

                }
            });

    byte[] data = zkCli.getData("/hello", new Watcher() {
        // 監聽的具體內容
        @Override
        public void process(WatchedEvent event) {
            System.out.println("監聽路徑為:" + event.getPath());
            System.out.println("監聽的型別為:" + event.getType());
            System.out.println("監聽被修改了!!!");
        }
    }, null);

    System.out.println(new String(data));
    Thread.sleep(Long.MAX_VALUE);
}

}

2、監聽目錄

複製程式碼
package com.css.zk;

import java.io.IOException;
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 WatchDemo1 {

static List<String> children = null;

public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
    ZooKeeper zkCli = new ZooKeeper("192.168.146.132:2181,192.168.146.133:2181,192.168.146.134:2181", 3000,
            new Watcher() {
                // 監聽回撥
                @Override
                public void process(WatchedEvent event) {
                    System.out.println("正在監聽中......");
                }
            });

    // 監聽目錄
    children = zkCli.getChildren("/", new Watcher() {
        @Override
        public void process(WatchedEvent event) {
            System.out.println("監聽路徑為:" + event.getPath());
            System.out.println("監聽的型別為:" + event.getType());
            System.out.println("監聽被修改了!!!");
            for (String c : children) {
                System.out.println(c);
            }
        }
    });
    Thread.sleep(Long.MAX_VALUE);
}

}

五、Zookeeper動態上下線感知系統

需求

某分散式系統當中,主節點有多臺,可以進行動態上下線,當有任何一臺機器發生了動態的上下線 任何一臺客戶端都能感知到。

思路

(1)建立客戶端與服務端
(2)啟動client端 監聽
(3)啟動server端 註冊
(4)當server端 發生上下線
(5)client端都能感知到

1、服務端

package com.css.serverclient;

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.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class ZkServer {
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
// 1.連線zkServer
ZkServer zkServer = new ZkServer();
zkServer.getConnect();

    // 2.註冊節點資訊 伺服器ip新增到zk中
    zkServer.regist(args[0]);

    // 3.業務邏輯處理
    zkServer.build(args[0]);
}

private String connectString = "192.168.146.132:2181,192.168.146.133:2181,192.168.146.134:2181";
private int sessionTimeout = 3000;
ZooKeeper zkCli = null;
// 定義父節點
private String parentNode = "/servers";

// 1.連線zkServer
public void getConnect() throws IOException {
    zkCli = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

        @Override
        public void process(WatchedEvent event) {

        }
    });
}

// 2.註冊資訊
public void regist(String hostname) throws KeeperException, InterruptedException {
    String node = zkCli.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE,
            CreateMode.EPHEMERAL_SEQUENTIAL);
    System.out.println(node);
}

// 3.構造伺服器
public void build(String hostname) throws InterruptedException {
    System.out.println(hostname + ":伺服器上線了!");
    Thread.sleep(Long.MAX_VALUE);
}

}

2、客戶端

package com.css.serverclient;

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 ZkClient {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
// 1.獲取連線
ZkClient zkClient = new ZkClient();
zkClient.getConnect();

    // 2.監聽服務的節點資訊
    zkClient.getServers();

    // 3.業務邏輯(一直監聽)
    zkClient.getWatch();
}

// 3.業務邏輯
public void getWatch() throws InterruptedException {
    Thread.sleep(Long.MAX_VALUE);
}

// 2.監聽服務的節點資訊
public void getServers() throws KeeperException, InterruptedException {
    List<String> children = zkCli.getChildren("/servers", true);
    ArrayList<String> serverList = new ArrayList<String>();

    // 獲取每個節點的資料
    for (String c : children) {
        byte[] data = zkCli.getData("/servers/" + c, true, null);
        serverList.add(new String(data));
    }

    // 列印伺服器列表
    System.out.println(serverList);
}

private String connectString = "192.168.146.132:2181,192.168.146.133:2181,192.168.146.134:2181";
private int sessionTimeout = 3000;
ZooKeeper zkCli = null;

// 1.連線叢集
public void getConnect() throws IOException {
    zkCli = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

        @Override
        public void process(WatchedEvent event) {
            List<String> children = null;
            try {
                // 監聽父節點
                children = zkCli.getChildren("/servers", true);

                // 建立集合儲存伺服器列表
                ArrayList<String> serverList = new ArrayList<String>();

                // 獲取每個節點的資料
                for (String c : children) {
                    byte[] data = zkCli.getData("/servers/" + c, true, null);
                    serverList.add(new String(data));
                }

                // 列印伺服器列表
                System.out.println(serverList);
            } catch (KeeperException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
}

}

3、只啟動客戶端時,控制檯輸出為:

在這裡插入圖片描述

此時客戶端控制檯輸出:

在這裡插入圖片描述

4、同時啟動客戶端和服務端

服務端執行
在這裡插入圖片描述
在這裡插入圖片描述

此時服務端輸出:

!](https://img-blog.csdnimg.cn/20201210113450671.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0Zsb2F0aW5nc2hlbg==,size_16,color_FFFFFF,t_70)

客戶端輸出:

在這裡插入圖片描述

相關文章