一、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、同時啟動客戶端和服務端
服務端執行
此時服務端輸出:
客戶端輸出:
這樣就實現了簡單的動態上下線感知。