上一篇文章,咱們講解了 ZooKeeper 入門知識,這篇文章主要講解下 ZooKeeper 的架構,理解 ZooKeeper 的架構能夠幫助咱們更好地設計協同服務。java
首先咱們來看下 ZooKeeper 的整體架構圖。node
應用使用 ZooKeeper 客戶端庫來使用 ZooKeeper 服務,ZooKeeper 客戶端會和集羣中某一個節點創建 session, ZooKeeper 客戶端負責和 ZooKeeper 集羣的交互。ZooKeeper 集羣能夠有兩種模式:standalone 模式和 quorum 模式。處於 standalone 模式的 ZooKeeper 集羣還有一個獨立運行的 ZooKeeper 節點,standalone 模式通常用來開發。實際生產環境 ZooKeeper 通常處於 quorum 模式,在 quorum 模式下 ZooKeeper 集羣包換多個 ZooKeeper 節點。數據庫
Session 是 ZooKeeper 客戶端的一個重要概念,ZooKeeper 客戶端庫和 ZooKeeper 集羣中的節點建立一個 session。客戶端能夠主動關閉 session。另外若是 ZooKeeper 節點沒有在 session 關聯的 timeout 時間內收到客戶端的數據的話,ZooKeeper 節點也會關閉 session。另外 ZooKeeper 客戶端庫若是發現鏈接的 ZooKeeper 出錯,會自動的和其餘 ZooKeeper 節點創建鏈接。apache
下圖展現了 ZooKeeper 客戶端是如何進行重連的?服務器
剛開始 ZooKeeper 客戶端和 ZooKeeper 集羣中的節點 1 創建的 session,在過了一段時間後,ZooKeeper 節點 1 失敗了,ZooKeeper 客戶端就自動和 ZooKeeper 集羣中的節點 3 從新創建了 session 鏈接。session
處於 Quorum 模式的 ZooKeeper 集羣包含多個 ZooKeeper 節點。下圖的 ZooKeeper 集羣有 3 個節點,其中節點 1 是 leader 節點,節點 2 和節點 3 是 follower 節點。集羣中只能有一個 leader 節點,能夠有多個 follower 節點,leader 節點能夠處理讀寫請求,follower 只能夠處理讀請求。follower 在接到寫請求時會把寫請求轉發給 leader 來處理。架構
下面來講下 ZooKeeper 保證的數據一致性:socket
數據一致性ide
爲了讓你們更好地理解 Quorum 模式,下面會配置一個 3 節點的 Quorum 模式的 ZooKeeper 集羣。.net
首先須要準備 3 個配置文件,dataDir 和 clientPort 配置項要配置不一樣的值。3 個配置文件的 server.n 部分都是同樣的。在 server.1=127.0.0.1:3333:3334,其中 3333 是 quorum 之間的通訊的端口號,3334 是用於 leader 選舉的端口號。
還須要在每一個節點的 dataDir 目錄下建立 myid 文件,裏面內容爲一個數字,用來標識當前主機,配置文件中配置的 server.n 中 n 爲何數字,則 myid 文件中就輸入這個數字。
以下是第 1 個節點的配置文件,其中目錄是 node1,端口號用的是 2181,另外兩個節點的目錄分別是 node2 和 node3,端口號分別爲 2182 和 2183,最下面的三行都是同樣的:
# 心跳檢查的時間 2秒 tickTime=2000 # 初始化時 鏈接到服務器端的間隔次數,總時間10*2=20秒 initLimit=10 # ZK Leader 和follower 之間通信的次數,總時間5*2=10秒 syncLimit=5 # 存儲內存中數據庫快照的位置,若是不設置參數,更新事務日誌將被存儲到默認位置。 dataDir=/data/zk/quorum/node1 # ZK 服務器端的監聽端口 clientPort=2181 server.1=127.0.0.1:3333:3334 server.2=127.0.0.1:4444:4445 server.3=127.0.0.1:5555:5556
下面來啓動這個集羣,首先啓動第一個節點,啓動命令以下:
zkServer.sh start-foreground /usr/local/apache-zookeeper-3.5.6-bin/conf/zoo-quorum-node1.cfg
注:start-foreground 選項 zkServer.sh 在前臺運行,把日誌直接打到 console。若是把日誌打到文件的話,這三個 zkServer.sh 會把日誌打到同一個文件。
在啓動第一個節點後日志中會出現以下:
2019-12-29 13:14:35,758 [myid:1] - WARN [WorkerSender[myid=1]:QuorumCnxManager@679] - Cannot open channel to 2 at election address /127.0.0.1:4445 java.net.ConnectException: Connection refused (Connection refused) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:650) at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:707) at org.apache.zookeeper.server.quorum.QuorumCnxManager.toSend(QuorumCnxManager.java:620) at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.process(FastLeaderElection.java:477) at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.run(FastLeaderElection.java:456) at java.lang.Thread.run(Thread.java:748)
緣由是配置文件中配置的爲 3 個節點,可是隻啓動了 1 個節點,目前他和其餘另外兩個節點創建不了鏈接,因此報這個問題。
接下來啓動第 2 個節點,執行命令以下:
zkServer.sh start-foreground /usr/local/apache-zookeeper-3.5.6-bin/conf/zoo-quorum-node2.cfg
啓動後,咱們能夠在節點 2 的日誌中發現這麼一行:
2019-12-29 13:15:13,699 [myid:2] - INFO [QuorumPeer[myid=2](plain=/0.0.0.0:2182)(secure=disabled):Leader@464] - LEADING - LEADER ELECTION TOOK - 41 MS
這說明節點 2 成爲了 leader 節點,一樣能夠在節點 1 的日誌中發現以下一行日誌,說明了節點 1 成爲了 follower 節點。
2019-12-29 13:15:13,713 [myid:1] - INFO [QuorumPeer[myid=1](plain=/0.0.0.0:2181)(secure=disabled):Follower@69] - FOLLOWING - LEADER ELECTION TOOK - 61 MS
由於對於一個三節點集羣來講兩個就表明了多數,就造成了 Quorum 模式,接下來啓動第 3 個節點,執行命令以下:
zkServer.sh start-foreground /usr/local/apache-zookeeper-3.5.6-bin/conf/zoo-quorum-node3.cfg
啓動後在日誌中也有以下一行,說明第 3 個節點也加入這個集羣,而且是做爲 follower 節點加入的。
2019-12-29 13:15:52,440 [myid:3] - INFO [QuorumPeer[myid=3](plain=/0.0.0.0:2183)(secure=disabled):Follower@69] - FOLLOWING - LEADER ELECTION TOOK - 15 MS
下面來啓動客戶端來使用這個三節點集羣,在命令中加了 -server 選項,後面指定的是三個節點的主機名和端口號,命令以下:
zkCli.sh -server 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
2019-12-29 13:45:44,982 [myid:127.0.0.1:2181] - INFO [main-SendThread(127.0.0.1:2181):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x101fff740830000, negotiated timeout = 30000
經過啓動日誌能夠看到客戶端和端口號爲 2181 的節點創建了鏈接,也就是和第 1 個節點創建了鏈接。
咱們執行 ls -R / 命令看下這個集羣中的 znode 數據。
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 1] ls -R / / /zookeeper /zookeeper/config /zookeeper/quota
下面咱們殺掉一個 ZooKeeper 節點,看客戶端是否能進行重連。如今咱們連的節點 1,咱們來把節點 1 殺掉,能夠在客戶端的日誌中發現客戶端和端口號爲 2183 的節點從新創建了鏈接,也就是和節點 3 創建了鏈接。
2019-12-29 14:03:31,392 [myid:127.0.0.1:2183] - INFO [main-SendThread(127.0.0.1:2183):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/127.0.0.1:2183, sessionid = 0x101fff740830000, negotiated timeout = 30000
而後咱們再看下客戶端可否正常使用,執行 ls -R / ,能夠發現可以正常返回數據,說明客戶端是可以正常使用的。
[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 4] ls -R / / /zookeeper /zookeeper/config /zookeeper/quota
這篇文章主要講解了 ZooKeeper 架構,以及怎樣配置一個三節點的 ZooKeeper 集羣。
完
●ZooKeeper 入門看這篇就夠了
●Nginx 熱部署和日誌切割,你學會了嗎?
●Nginx 瞭解一下?
●你真的瞭解 volatile 關鍵字嗎?
●Java線程的生老病死
●Java 8 Optional:優雅地避免 NPE
武培軒有幫助?在看,轉發走一波喜歡做者