1. 程式人生 > >架構設計 | 分散式系統排程,Zookeeper叢集化管理

架構設計 | 分散式系統排程,Zookeeper叢集化管理

本文原始碼:[GitHub·點這裡](https://github.com/cicadasmile/data-manage-parent) || [GitEE·點這裡](https://gitee.com/cicadasmile/data-manage-parent) # 一、框架簡介 ## 1、基礎簡介 Zookeeper基於觀察者模式設計的元件,主要應用於分散式系統架構中的,統一命名服務、統一配置管理、統一叢集管理、伺服器節點動態上下線、軟負載均衡等場景。 - [Linux下Zookeeper單節點安裝](https://mp.weixin.qq.com/s/NsWZN5zScFKgBanzSg224g) - [SpringBoot整合Zookeeper中介軟體](https://mp.weixin.qq.com/s/zjw-A7u-chGZhNgwuUsEPw) ## 2、叢集選舉 Zookeeper叢集基於半數機制,叢集中半數以上機器存活,叢集處於可用狀態。所以建議Zookeeper叢集安裝為奇數臺伺服器。在叢集的配置檔案中並沒有指定Master和Slave。在Zookeeper工作時,是有一個節點為Leader,其他則為Follower,Leader是通過內部的選舉機制臨時產生的。 ![](https://img2020.cnblogs.com/blog/1691717/202005/1691717-20200510233814575-1695698996.png) **基本描述** 假設有三臺伺服器組成的Zookeeper叢集,每個節點的myid編號依次1-3,依次啟動伺服器,會發現server2被選擇為Leader節點。 server1啟動,執行一次選舉。伺服器1投自己一票。此時伺服器1票數一票,未達到半數以上(2票),選舉無法完成,伺服器1狀態保持為LOOKING; server2啟動,再執行一次選舉。伺服器1和2分別投自己一票,並交換選票資訊,因為伺服器2的myid比伺服器1的myid大,伺服器1會更改選票為投伺服器2。此時伺服器1票數0票,伺服器2票數2票,達到半數以上,選舉完成,伺服器1狀態為follower,2狀態保持leader,此時叢集可用,伺服器3啟動後直接為follower。 # 二、叢集配置 ## 1、建立配置目錄 ``` # mkdir -p /data/zookeeper/data # mkdir -p /data/zookeeper/logs ``` ## 2、基礎配置 ``` # vim /opt/zookeeper-3.4.14/conf/zoo.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=/data/zookeeper/data dataLogDir=/data/zookeeper/logs clientPort=2181 ``` ## 3、單節點配置 ``` # vim /data/zookeeper/data/myid ``` 三個節點服務,分別在myid檔案中寫入[1,2,3] ## 4、叢集服務 在每個服務的zoo.cfg配置檔案中寫入如下配置: ``` server.1=192.168.72.133:2888:3888 server.2=192.168.72.136:2888:3888 server.3=192.168.72.137:2888:3888 ``` ## 5、啟動叢集 分別啟動三臺zookeeper服務 ``` [zookeeper-3.4.14]# bin/zkServer.sh start Starting zookeeper ... STARTED ``` ## 6、檢視叢集狀態 Mode: leader是Master節點 Mode: follower是Slave節點 ``` [zookeeper-3.4.14]# bin/zkServer.sh status Mode: leader ``` ## 7、叢集狀態測試 隨便登入一臺服務的客戶端,建立一個測試節點,然後在其他服務上檢視。 ``` [zookeeper-3.4.14 bin]# ./zkCli.sh [zk: 0] create /node-test01 node-test01 Created /node-test01 [zk: 1] get /node-test01 ``` 或者關閉leader節點 ``` [zookeeper-3.4.14 bin]# ./zkServer.sh stop ``` 則會重新選舉該節點。 ## 8、Nginx統一管理 ``` [rnginx-1.15.2 conf]# vim nginx.conf stream { upstream zkcluster { server 192.168.72.133:2181; server 192.168.72.136:2181; server 192.168.72.136:2181; } server { listen 2181; proxy_pass zkcluster; } } ``` # 三、服務節點監聽 ## 1、基本原理 分散式系統中,主節點可以有多臺,可以動態上下線,任意一臺客戶端都能實時感知到主節點伺服器的上下線。 ![](https://img2020.cnblogs.com/blog/1691717/202005/1691717-20200510233802104-652576202.png) 流程描述: - 啟動Zookeeper叢集服務; - RegisterServer模擬服務端註冊; - ClientServer模擬客戶端監聽; - 啟動服務端註冊三次,註冊不同節點的zk-node服務; - 依次關閉註冊的服務端,模擬服務下線流程; - 檢視客戶端日誌,可以監控到服務節點變化; 首先建立一個節點:serverList,用來存放伺服器列表。 ``` [zk: 0] create /serverList "serverList" ``` ## 2、服務端註冊 ```java package com.zkper.cluster.monitor; 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 RegisterServer { private ZooKeeper zk ; private static final String connectString = "127.0.0.133:2181,127.0.0.136:2181,127.0.0.137:2181"; private static final int sessionTimeout = 3000; private static final String parentNode = "/serverList"; private void getConnect() throws IOException{ zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent event) { } }); } private void registerServer(String nodeName) throws Exception{ String create = zk.create(parentNode + "/server", nodeName.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); System.out.println(nodeName +" 上線:"+ create); } private void working() throws Exception{ Thread.sleep(Long.MAX_VALUE); } public static void main(String[] args) throws Exception { RegisterServer server = new RegisterServer(); server.getConnect(); // 分別啟動三次服務,註冊不同節點,再一次關閉不同服務端看客戶端效果 // server.registerServer("zk-node-133"); // server.registerServer("zk-node-136"); server.registerServer("zk-node-137"); server.working(); } } ``` ## 3、客戶端監聽 ```java package com.zkper.cluster.monitor; import org.apache.zookeeper.*; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class ClientServer { private ZooKeeper zk ; private static final String connectString = "127.0.0.133:2181,127.0.0.136:2181,127.0.0.137:2181"; private static final int sessionTimeout = 3000; private static final String parentNode = "/serverList"; private void getConnect() throws IOException { zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent event) { try { // 監聽線上的服務列表 getServerList(); } catch (Exception e) { e.printStackTrace(); } } }); } private void getServerList() throws Exception {