Zookeeper簡介及使用


一、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:$PWD
    (8)修改myid依次為2 3
    (9)修改環境變量
    vi /etc/profile
    export ZOOKEEPER_HOME=/root/hd/zookeeper3.4.10
    export PATH=$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、同時啟動客戶端和服務端

 服務端執行

此時服務端輸出:

客戶端輸出:

這樣就實現了簡單的動態上下線感知。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM