zookeeper如何管理服務和配置
A. zookeeper跟php結合做服務配置的處理 該怎麼處理
Zookper: 一種分布式應用的協作服務
Zookper是一種分布式的,開源的,應用於分布式應用的協作服務。它提供了一些簡單的操作,使得分布式應用可以基於這些介面實現諸如同步、配置維護和分集群或者命名的服務。Zookper很容易編程接入,它使用了一個和文件樹結構相似的數據模型。可以使用java或者C來進行編程接入。
眾所周知,分布式的系統協作服務很難有讓人滿意的產品。這些協作服務產品很容易陷入一些諸如競爭選擇條件或者死鎖的陷阱中。Zookper的目的就是將分布式服務不再需要由於協作沖突而另外實現協作服務。
設計目標 Zookeeper是簡易的
Zookeeper通過一種和文件系統很像的層級命名空間來讓分布式進程互相協同工作。這些命名空間由一系列數據寄存器組成,我們也叫這些數據寄存器為znodes。這些znodes就有點像是文件系統中的文件和文件夾。和文件系統不一樣的是,文件系統的文件是存儲在存儲區上的,而zookeeper的數據是存儲在內存上的。同時,這就意味著zookeeper有著高吞吐和低延遲。
Zookeeper實現了高性能,高可靠性,和有序的訪問。高性能保證了zookeeper能應用在大型的分布式系統上。高可靠性保證它不會由於單一節點的故障而造成任何問題。有序的訪問能保證客戶端可以實現較為復雜的同步操作。
Zookeeper是可重用的
ZooKeeper Service
image
組成Zookeeper的各個伺服器必須要能相互通信。他們在內存中保存了伺服器狀態,也保存了操作的日誌,並且持久化快照。只要大多數的伺服器是可用的,那麼Zookeeper就是可用的。
客戶端連接到一個Zookeeper伺服器,並且維持TCP連接。並且發送請求,獲取回復,獲取事件,並且發送連接信號。如果這個TCP連接斷掉了,那麼客戶端可以連接另外一個伺服器。
Zookeeper是有序的
Zookeeper使用數字來對每一個更新進行標記。這樣能保證Zookeeper交互的有序。後續的操作可以根據這個順序實現諸如同步操作這樣更高更抽象的服務。
Zookeeper是高效的
Zookeeper的高效更表現在以讀為主的系統上。Zookeeper可以在千台伺服器組成的讀寫比例大約為10:1的分布系統上表現優異。
數據結構和分等級的命名空間
Zookeeper的命名空間的結構和文件系統很像。一個名字和文件一樣使用/的路徑表現,zookeeper的每個節點都是被路徑唯一標識
ZooKeeper's Hierarchical Namespace
image
實現
下圖顯示了ZooKeeper服務的高級組件服務。除了請求處理器,Zookeeper伺服器組的每個伺服器復制他們自己的每個組件。
ZooKeeper Components
image
replicated database是一個存儲在內存中的包含整個數據樹的結構。所有的更新操作都做日誌到硬碟上了。並且寫操作在作用在資料庫的時候會序列化存儲到硬碟上。
每個ZooKeeper伺服器都連接了許多個客戶端。客戶端連接到一個伺服器來提交請求。
B. 如何管理zookeeper配置文件
(1)解壓為zookeepertar -xf -C /home/myuser/zookeeper/ 復制zookeeper文件夾3份,分別重名名為zookeeperA,zookeeperB,zookeeperC。 並且創建數據快照以及日誌存放文件夾,命名為zooA護觸篙吠蕻杜戈森恭緝,zooB,zooC。
C. 怎麼zookeeper管理工具
ZooKeeper作為發現服務的問題
ZooKeeper(註:ZooKeeper是著名Hadoop的一個子項目,旨在解決大規模分
布式應用場景下,服務協調同步(Coordinate
Service)的問題;它可以為同在一個分布式系統中的其他服務提供:統一命名服務、配置管理、分布式鎖服務、集群管理等功能)是個偉大的開源項目,它
很成熟,有相當大的社區來支持它的發展,而且在生產環境得到了廣泛的使用;但是用它來做Service發現服務解決方案則是個錯誤。
D. Zookeeper 理論基礎
ZooKeeper 由雅虎研究院開發,後來捐贈給了 Apache。ZooKeeper 是一個開源的分布式應用程序協調伺服器,其為分布式系統提供一致性服務。其一致性是通過基於 Paxos 演算法的ZAB 協議完成的。其主要功能包括:配置維護、域名服務、分布式同步、集群管理等。
zookeeper 的官網: http://zookeeper.apache.org
zk 是如何保證分布式系統的一致性的呢?是因為 zk 具有以下幾方面的特點:
對於zk 理論的學習,最重要也是最難的知識點就是 Paxos 演算法。所以我們首先學習 Paxos演算法。
Paxos 演算法是萊斯利·蘭伯特(Leslie Lamport)1990 年提出的一種基於消息傳遞的、具有高容錯性的一致性演算法。Google Chubby 的作者 Mike Burrows 說過,世上只有一種一致性演算法, 那就是 Paxos,所有其他一致性演算法都是 Paxos 演算法的不完整版。Paxos 演算法是一種公認的晦澀難懂的演算法,並且工程實現上也具有很大難度。較有名的 Paxos 工程實現有Google Chubby、ZAB、微信的 PhxPaxos 等。
Paxos 演算法是用於解決什麼問題的呢?Paxos 演算法要解決的問題是,在分布式系統中如何就某個決議達成一致。
拜占庭將軍問題是由 Paxos 演算法作者萊斯利·蘭伯特提出的點對點通信中的基本問題。該問題要說明的含義是,在不可靠信道上試圖通過消息傳遞的方式達到一致性是不可能的。所以,Paxos 演算法的前提是不存在拜占庭將軍問題,即信道是安全的、可靠的,集群節點間傳遞的消息是不會被篡改的。
一般情況下,分布式系統中各個節點間採用兩種通訊模型:共享內存(Shared Memory)、消息傳遞(Messages Passing)。而 Paxos 是基於消息傳遞通訊模型的。
在 Paxos 演算法中有三種角色,分別具有三種不同的行為。但很多時候,一個進程可能同時充當著多種角色。
Paxos 演算法的一致性主要體現在以下幾點:
Paxos 對於提案的提交演算法有兩種方案,2PC 與 3PC。
它們的區別主要就在於 accept 階段中是否包含 commit 功能。具體看下面的描述。
Paxos 演算法的 3PC 執行過程劃分為三個階段:准備階段 prepare、接受階段 accept,與提交階段 commit。
若提案者接收到的反饋數量超過了半數,則其會向外廣播兩類信息:
2PC 與 3PC 的區別是,在提案者接收到超過半數的表決者對於 parepare 階段的反饋後,其會向所有表決者發送真正的提案 proposal。當表決者接受到 proposal 後就直接將其同步到了本地,不用再等待 commit 消息了。
那麼,為什麼不直接使用 2PC,而要使用 3PC 呢?是因為 2PC 中存在著較多的弊端(這里就不再展開來說了)。所以很多 Paxos 工業實現使用的都是 3PC 提交。但 2PC 提交的效率要高於 3PC 提交,所以在保證不出問題的情況下,是可以使用 2PC 提交的。
前面所述的Paxos 演算法在實際工程應用過程中,根據不同的實際需求存在諸多不便之處, 所以也就出現了很多對於基本 Paxos 演算法的優化演算法,以對 Paxos 演算法進行改進,例如,Multi Paxos、Fast Paxos、EPaxos。
例如,Paxos 演算法存在「活鎖問題」,Fast Paxos 演算法對 Paxos 演算法進行了改進:只允許一個進程提交提案,即該進程具有對 N 的唯一操作權。該方式解決了「活鎖」問題。
ZAB ,Zookeeper Atomic Broadcast,zk 原子消息廣播協議,是專為 ZooKeeper 設計的一種支持崩潰恢復的原子廣播協議,在 Zookeeper 中,主要依賴 ZAB 協議來實現分布式數據一致性。
Zookeeper 使用一個單一主進程來接收並處理客戶端的所有事務請求,即寫請求。當伺服器數據的狀態發生變更後,集群採用 ZAB 原子廣播協議,以事務提案 Proposal 的形式廣播到所有的副本進程上。ZAB 協議能夠保證一個全局的變更序列,即可以為每一個事務分配一個全局的遞增編號 xid。
當 Zookeeper 客戶端連接到 Zookeeper 集群的一個節點後,若客戶端提交的是讀請求, 那麼當前節點就直接根據自己保存的數據對其進行響應;如果是寫請求且當前節點不是Leader,那麼節點就會將該寫請求轉發給 Leader,Leader 會以提案的方式廣播該寫操作,只要有超過半數節點同意該寫操作,則該寫操作請求就會被提交。然後 Leader 會再次廣播給所有訂閱者,即 Learner,通知它們同步數據。
ZAB 協議是 Paxos 演算法的一種工業實現演算法。但兩者的設計目標不太一樣。ZAB 協議主要用於構建一個高可用的分布式數據主從系統,即 Follower 是 Leader 的從機,Leader 掛了, 馬上就可以選舉出一個新的 Leader,但平時它們都對外提供服務。而 Fast Paxos 演算法則是用於構建一個分布式一致性狀態機系統,確保系統中各個節點的狀態都是一致的。
另外,ZAB 還使用 Google 的 Chubby 演算法作為分布式鎖的實現,而 Google 的 Chubby 也是 Paxos 演算法的應用。
zk 集群對於事務請求的處理是 Fast Paxos 演算法的體現,即只允許 Leader 提出提案。其屬於 3PC 提交。
但 Leader 選舉是 Paxos 演算法的體現,因為 Leader 宕機後,所有 Follower 均可提交提案, 它們在最初都是「我選我」。其屬於 2PC 提交。
為了避免 Zookeeper 的單點問題,zk 也是以集群的形式出現的。zk 集群中的角色主要有以下三類:
Learner:學習者,同步者。
Learner = Follower + Observer
QuorumPeer = Participant = Leader + Follower
在 ZAB 中有三個很重要的數據:
ZAB 協議中對zkServer 的狀態描述有三種模式。這三種模式並沒有十分明顯的界線,它們相互交織在一起。
zk 集群中的每一台主機,在不同的階段會處於不同的狀態。每一台主機具有四種狀態。
在集群啟動過程中,或 Leader 宕機後,集群就進入了恢復模式。恢復模式中最重要的階段就是 Leader 選舉。
A、serverId
這是zk 集群中伺服器的唯一標識,也稱為 sid,其實質就是 zk 中配置的 myid。例如, 有三個 zk 伺服器,那麼編號分別是 1,2,3。
B、 邏輯時鍾
邏輯時鍾,Logicalclock,是一個整型數,該概念在選舉時稱為 logicalclock,而在選舉結束後稱為epoch。即 epoch 與 logicalclock 是同一個值,在不同情況下的不同名稱。
在集群啟動過程中的 Leader 選舉過程(演算法)與 Leader 斷連後的 Leader 選舉過程稍微有一些區別,基本相同。
A、集群啟動中的 Leader 選舉
對於 Server1 而言,它的投票是(1, 0),接收 Server2 的投票為(2, 0)。其首先會比較兩者的 ZXID,均為 0,再比較 myid,此時 Server2 的 myid 最大,於是 Server1 更新自己的投票為(2, 0),然後重新投票。對於 Server2 而言,其無須更新自己的投票,只是再次向集群中所有主機發出上一次投票信息即可。
(4) 統計投票。每次投票後,伺服器都會統計投票信息,判斷是否已經有過半機器接受到相同的投票信息。對於 Server1、Server2 而言,都統計出集群中已經有兩台主機接受了(2, 0)的投票信息,此時便認為已經選出了新的 Leader,即 Server2。
(5) 改變伺服器狀態。一旦確定了 Leader,每個伺服器就會更新自己的狀態,如果是Follower,那麼就變更為 FOLLOWING,如果是 Leader,就變更為 LEADING。
(6) 添加主機。在新的 Leader 選舉出來後 Server3 啟動,其想發出新一輪的選舉。但由於當前集群中各個主機的狀態並不是 LOOKING,而是各司其職的正常服務,所以其只能是以Follower 的身份加入到集群中。
B、 宕機後的 Leader 選舉
在 Zookeeper 運行期間,Leader 與非 Leader 伺服器各司其職,即便當有非 Leader 伺服器宕機或新加入時也不會影響 Leader。但是若 Leader 伺服器掛了,那麼整個集群將暫停對外服務,進入新一輪的 Leader 選舉,其過程和啟動時期的 Leader 選舉過程基本一致。
前面我們說過,恢復模式具有兩個階段:Leader 選舉與初始化同步。當完成 Leader 選舉後,此時的 Leader 還是一個准 Leader,其要經過初始化同步後才能變為真正的 Leader。
具體過程如下:
當集群中的 Learner 完成了初始化狀態同步,那麼整個 zk 集群就進入到了正常工作模式了。
如果集群中的 Learner 節點收到客戶端的事務請求,那麼這些 Learner 會將請求轉發給Leader 伺服器。然後再執行如下的具體過程:
Observer 數量並不是越多越好,一般與 Follower 數量相同。因為 Observer 數量的增多雖不會增加事務操作壓力,但其需要從 Leader 同步數據,Observer 同步數據的時間是小於等於 Follower 同步數據的時間的。當 Follower 同步數據完成,Leader 的 Observer 列表中的Observer 主機將結束同步。那些完成同步的 Observer 將會進入到另一個對外提供服務的列表。那麼,那些沒有同步了數據無法提供服務的 Observer 主機就形成了資源浪費。
所以,對於事務操作發生頻繁的系統,不建議使用過多的 Observer。
Leader 中保存的 Observer 列表其實有兩個:
all:包含所有 Observer。
service:已經完成了從 Leader 同步數據的任務。service <= all。其是動態的。
Leader 中保存的 Follower 列表其實也有兩個:
all:要求其中必須有過半的 Follower 向Leader 反饋ACK
service:
當集群正在啟動過程中,或 Leader 崩潰後,集群就進入了恢復模式。對於要恢復的數據狀態需要遵循三個原則。
若集群中 Leader 收到的 Follower 心跳數量沒有過半,此時 Leader 會自認為自己與集群的連接已經出現了問題,其會主動修改自己的狀態為 LOOKING,去查找新的 Leader。
而其它 Server 由於有過半的主機認為已經丟失了 Leader,所以它們會發起新的 Leader選舉,選出一個新的 Leader。
正常情況下,當 Leader 收到超過半數 Follower 的 ACKs 後,就向各個 Follower 廣播COMMIT 消息,批准各個Server 執行該寫操作事務。當各個Server 在接收到Leader 的COMMIT 消息後就會在本地執行該寫操作,然後會向客戶端響應寫操作成功。
但是如果在非全部 Follower 收到 COMMIT 消息之前 Leader 就掛了,這將導致一種後果:部分 Server 已經執行了該事務,而部分 Server 尚未收到 COMMIT 消息,所以其並沒有執行該事務。當新的 Leader 被選舉出,集群經過恢復模式後需要保證所有 Server 上都執行了那些已經被部分 Server 執行過的事務。
當在 Leader 新事務已經通過,其已經將該事務更新到了本地,但所有 Follower 還都沒有收到 COMMIT 之前,Leader 宕機了,此時,所有 Follower 根本就不知道該 Proposal 的存在。當新的 Leader 選舉出來,整個集群進入正常服務狀態後,之前掛了的 Leader 主機重新啟動並注冊成為了 Follower。若那個別人根本不知道的 Proposal 還保留在那個主機,那麼其數據就會比其它主機多出了內容,導致整個系統狀態的不一致。所以,該 Proposa 應該被丟棄。類似這樣應該被丟棄的事務,是不能再次出現在集群中的,應該被清除。
前面我們說過,無論是寫操作投票,還是 Leader 選舉投票,都必須過半才能通過,也就是說若出現超過半數的主機宕機,則投票永遠無法通過。基於該理論,由 5 台主機構成的集群,最多隻允許 2 台宕機。而由 6 台構成的集群,其最多也只允許 2 台宕機。即,6 台與5 台的容災能力是相同的。基於此容災能力的原因,建議使用奇數台主機構成集群,以避免資源浪費。
但從系統吞吐量上說,6 台主機的性能一定是高於 5 台的。所以使用 6 台主機並不是資源浪費。
對於一個高可用的系統,除了要設置多台主機部署為一個集群避免單點問題外,還需要考慮將集群部署在多個機房、多個樓宇。對於多個機房、樓宇中集群也是不能隨意部署的, 下面就多個機房的部署進行分析。
在多機房部署設計中,要充分考慮「過半原則」,也就是說,盡量要確保 zk 集群中有過半的機器能夠正常運行。
在生產環境下,三機房部署是最常見的、容災性最好的部署方案。三機房部署中要求每個機房中的主機數量必須少於集群總數的一半。
zk 官方沒有給出較好的雙機房部署的容災方案。只能是讓其中一個機房佔有超過半數的主機,使其做為主機房,而另一機房少於半數。當然,若主機房出現問題,則整個集群會癱瘓。
CAP 定理又稱 CAP 原則,指的是在一個分布式系統中,Consistency(一致性)、Availability(可用性)、Partition tolerance(分區容錯性),三者不可兼得。
對於分布式系統,網路環境相對是不可控的,出現網路分區是不可避免的,因此系統必須具備分區容錯性。但其並不能同時保證一致性與可用性。CAP 原則對於一個分布式系統來說,只可能滿足兩項,即要麼 CP,要麼 AP。
BASE 是Basically Available(基本可用)、Soft state(軟狀態)和 Eventually consistent(最終一致性)三個短語的簡寫。
BASE 理論的核心思想是:即使無法做到實時一致性,但每個系統都可以根據自身的業務特點,採用適當的方式來使系統達到最終一致性。
基本可用是指分布式系統在出現不可預知故障的時候,允許損失部分可用性。
損失響應時間:
損失功能:
軟狀態,是指允許系統數據存在的中間狀態,並認為該中間狀態的存在不會影響系統的整體可用性,即允許系統主機間進行數據同步的過程存在一定延時。軟狀態,其實就是一種灰度狀態,過渡狀態。
最終一致性強調的是系統中所有的數據副本,在經過一段時間的同步後,最終能夠達到一個一致的狀態。因此,最終一致性的本質是需要系統保證最終數據能夠達到一致,而不需要實時保證系統數據的一致性。
從達到一致性的時間角度來劃分,可以分為:
單從客戶端訪問到的內容角度來劃分,可以分為:
zk 遵循的是 CP 原則,即保證了一致性,但犧牲了可用性。體現在哪裡呢?
當 Leader 宕機後,zk 集群會馬上進行新的 Leader 的選舉。但選舉時長一般在 200 毫秒內,最長不超過 60 秒,整個選舉期間 zk 集群是不接受客戶端的讀寫操作的,即 zk 集群是處於癱瘓狀態的。所以,其不滿足可用性。
這里說的zk可能會引發腦裂,是指的在多機房部署中,若出現了網路連接問題,形成多個分區,則可能會出現腦裂問題,可能會導致數據不一致。
(1)情況一
(2)情況二
(5)情況五
E. Zookeeper在哪些系統中使用,又是怎麼用的
ZooKeeper作為發現服務的問題 ZooKeeper(註:ZooKeeper是著名Hadoop的一個子項目,旨在解決大規模分 布式應用場景下,服務協調同步(Coordinate Service)的問題;它可以為同在一個分布式系統中的其他服務提供:統一命名服務、配置管理、分布式鎖服務、集群管理等功能)是個偉大的開源項目,它 很成熟,有相當大的社區來支持它的發展,而且在生產環境得到了廣泛的使用;但是用它來做Service發現服務解決方案則是個錯誤。 在分布式系統領域有個著名的 CAP定理(C- 數據一致性;A-服務可用性;P-服務對網路分區故障的容錯性,這三個特性在任何分布式系統中不能同時滿足,最多同時滿足兩個);ZooKeeper是個 CP的,即任何時刻對ZooKeeper的訪問請求能得到一致的數據結果,同時系統對網路分割具備容錯性;但是它不能保證每次服務請求的可用性(註:也就 是在極端環境下,ZooKeeper可能會丟棄一些請求,消費者程序需要重新請求才能獲得結果)。但是別忘了,ZooKeeper是分布式協調服務,它的 職責是保證數據(註:配置數據,狀態數據)在其管轄下的所有服務之間保持同步、一致;所以就不難理解為什麼ZooKeeper被設計成CP而不是AP特性 的了,如果是AP的,那麼將會帶來恐怖的後果(註:ZooKeeper就像交叉路口的信號燈一樣,你能想像在交通要道突然信號燈失靈的情況嗎?)。而且, 作為ZooKeeper的核心實現演算法 Zab,就是解決了分布式系統下數據如何在多個服務之間保持同步問題的。 作為一個分布式協同服務,ZooKeeper非常好,但是對於Service發現服務來說就不合適了;因為對於Service發現服務來說就算 是 返回了包含不實的信息的結果也比什麼都不返回要好;再者,對於Service發現服務而言,寧可返回某服務5分鍾之前在哪幾個伺服器上可用的信息,也不能 因為暫時的網路故障而找不到可用的伺服器,而不返回任何結果。所以說,用ZooKeeper來做Service發現服務是肯定錯誤的,如果你這么用就慘 了! 而且更何況,如果被用作Service發現服務,ZooKeeper本身並沒有正確的處理網路分割的問題;而在雲端,網路分割問題跟其他類型的 故障一樣的確會發生;所以最好提前對這個問題做好100%的准備。就像 Jepsen在 ZooKeeper網站上發布的博客中所說:在ZooKeeper中,如果在同一個網路分區(partition)的節點數(nodes)數達不到 ZooKeeper選取Leader節點的「法定人數」時,它們就會從ZooKeeper中斷開,當然同時也就不能提供Service發現服務了。 如果給ZooKeeper加上客戶端緩存(註:給ZooKeeper節點配上本地緩存)或者其他類似技術的話可以緩解ZooKeeper因為網 絡故障造成節點同步信息錯誤的問題。 Pinterest與 Airbnb公 司就使用了這個方法來防止ZooKeeper故障發生。這種方式可以從表面上解決這個問題,具體地說,當部分或者所有節點跟ZooKeeper斷開的情況 下,每個節點還可以從本地緩存中獲取到數據;但是,即便如此,ZooKeeper下所有節點不可能保證任何時候都能緩存所有的服務注冊信息。如果 ZooKeeper下所有節點都斷開了,或者集群中出現了網路分割的故障(註:由於交換機故障導致交換機底下的子網間不能互訪);那麼ZooKeeper 會將它們都從自己管理范圍中剔除出去,外界就不能訪問到這些節點了,即便這些節點本身是「健康」的,可以正常提供服務的;所以導致到達這些節點的服務請求 被丟失了。(註:這也是為什麼ZooKeeper不滿足CAP中A的原因) 更深層次的原因是,ZooKeeper是按照CP原則構建的,也就是說它能保證每個節點的數據保持一致,而為ZooKeeper加上緩存的做法 的 目的是為了讓ZooKeeper變得更加可靠(available);但是,ZooKeeper設計的本意是保持節點的數據一致,也就是CP。所以,這樣 一來,你可能既得不到一個數據一致的(CP)也得不到一個高可用的(AP)的Service發現服務了;因為,這相當於你在一個已有的CP系統上強制栓了 一個AP的系統,這在本質上就行不通的!一個Service發現服務應該從一開始就被設計成高可用的才行! 如果拋開CAP原理不管,正確的設置與維護ZooKeeper服務就非常的困難;錯誤會 經常發生, 導致很多工程被建立只是為了減輕維護ZooKeeper的難度。這些錯誤不僅存在與客戶端而且還存在於ZooKeeper伺服器本身。Knewton平台 很多故障就是由於ZooKeeper使用不當而導致的。那些看似簡單的操作,如:正確的重建觀察者(reestablishing watcher)、客戶端Session與異常的處理與在ZK窗口中管理內存都是非常容易導致ZooKeeper出錯的。同時,我們確實也遇到過 ZooKeeper的一些經典bug: ZooKeeper-1159 與 ZooKeeper-1576; 我們甚至在生產環境中遇到過ZooKeeper選舉Leader節點失敗的情況。這些問題之所以會出現,在於ZooKeeper需要管理與保障所管轄服務 群的Session與網路連接資源(註:這些資源的管理在分布式系統環境下是極其困難的);但是它不負責管理服務的發現,所以使用ZooKeeper當 Service發現服務得不償失。 做出正確的選擇:Eureka的成功 我們把Service發現服務從ZooKeeper切換到了Eureka平台,它是一個開 源的服務發現解決方案,由Netflix公司開發。(註:Eureka由兩個組件組成:Eureka伺服器和Eureka客戶端。Eureka伺服器用作 服務注冊伺服器。Eureka客戶端是一個java客戶端,用來簡化與伺服器的交互、作為輪詢負載均衡器,並提供服務的故障切換支持。)Eureka一開 始就被設計成高可用與可伸縮的Service發現服務,這兩個特點也是Netflix公司開發所有平台的兩個特色。( 他們都在討論Eureka)。自從切換工作開始到現在,我們實現了在生產環境中所有依賴於Eureka的產品沒有下線維護的記錄。我們也被告知過,在雲平 台做服務遷移註定要遇到失敗;但是我們從這個例子中得到的經驗是,一個優秀的Service發現服務在其中發揮了至關重要的作用! 首先,在Eureka平台中,如果某台伺服器宕機,Eureka不會有類似於ZooKeeper的選舉leader的過程;客戶端請求會自動切 換 到新的Eureka節點;當宕機的伺服器重新恢復後,Eureka會再次將其納入到伺服器集群管理之中;而對於它來說,所有要做的無非是同步一些新的服務 注冊信息而已。所以,再也不用擔心有「掉隊」的伺服器恢復以後,會從Eureka伺服器集群中剔除出去的風險了。Eureka甚至被設計用來應付范圍更廣 的網路分割故障,並實現「0」宕機維護需求。當網路分割故障發生時,每個Eureka節點,會持續的對外提供服務(註:ZooKeeper不會):接收新 的服務注冊同時將它們提供給下游的服務發現請求。這樣一來,就可以實現在同一個子網中(same side of partition),新發布的服務仍然可以被發現與訪問。 但是,Eureka做到的不止這些。正常配置下,Eureka內置了心跳服務,用於淘汰一些「瀕死」的伺服器;如果在Eureka中注冊的服 務, 它的「心跳」變得遲緩時,Eureka會將其整個剔除出管理范圍(這點有點像ZooKeeper的做法)。這是個很好的功能,但是當網路分割故障發生時, 這也是非常危險的;因為,那些因為網路問題(註:心跳慢被剔除了)而被剔除出去的伺服器本身是很」健康「的,只是因為網路分割故障把Eureka集群分割 成了獨立的子網而不能互訪而已。 幸運的是,Netflix考慮到了這個缺陷。如果Eureka服務節點在短時間里丟失了大量的心跳連接(註:可能發生了網路故障),那麼這個 Eureka節點會進入」自我保護模式「,同時保留那些「心跳死亡「的服務注冊信息不過期。此時,這個Eureka節點對於新的服務還能提供注冊服務,對 於」死亡「的仍然保留,以防還有客戶端向其發起請求。當網路故障恢復後,這個Eureka節點會退出」自我保護模式「。所以Eureka的哲學是,同時保 留」好數據「與」壞數據「總比丟掉任何」好數據「要更好,所以這種模式在實踐中非常有效。 最後,Eureka還有客戶端緩存功能(註:Eureka分為客戶端程序與伺服器端程序兩個部分,客戶端程序負責向外提供注冊與發現服務接 口)。 所以即便Eureka集群中所有節點都失效,或者發生網路分割故障導致客戶端不能訪問任何一台Eureka伺服器;Eureka服務的消費者仍然可以通過 Eureka客戶端緩存來獲取現有的服務注冊信息。甚至最極端的環境下,所有正常的Eureka節點都不對請求產生相應,也沒有更好的伺服器解決方案來解 決這種問題時;得益於Eureka的客戶端緩存技術,消費者服務仍然可以通過Eureka客戶端查詢與獲取注冊服務信息,這點很重要。 Eureka的構架保證了它能夠成為Service發現服務。它相對與ZooKeeper來說剔除了Leader節點的選取或者事務日誌機制, 這 樣做有利於減少使用者維護的難度也保證了Eureka的在運行時的健壯性。而且Eureka就是為發現服務所設計的,它有獨立的客戶端程序庫,同時提供心 跳服務、服務健康監測、自動發布服務與自動刷新緩存的功能。但是,如果使用ZooKeeper你必須自己來實現這些功能。Eureka的所有庫都是開源 的,所有人都能看到與使用這些源代碼,這比那些只有一兩個人能看或者維護的客戶端庫要好。 維護Eureka伺服器也非常的簡單,比如,切換一個節點只需要在現有EIP下移除一個現有的節點然後添加一個新的就行。Eureka提供了一 個 web-based的圖形化的運維界面,在這個界面中可以查看Eureka所管理的注冊服務的運行狀態信息:是否健康,運行日誌等。Eureka甚至提供 了Restful-API介面,方便第三方程序集成Eureka的功能。
F. Zookeeper深入原理
Zookeeper 的視圖結構是一個樹形結構,樹上的每個節點稱之為數據節點(即 ZNode),每個ZNode 上都可以保存數據,同時還可以掛載子節點。並且Zookeeper的根節點為 "/"。
在 Zookeeper 中,每個數據節點都是有生命周期的,其生命周期的長短取決於數據節點的節點類型。在 Zookeeper 中有如下幾類節點:
每個數據節點中除了存儲了數據內容之外,還存儲了數據節點本身的一些狀態信息(State)。
在Zookeeper 中,事務是指能夠改變 Zookeeper 伺服器狀態的操作,我們也稱之為事務操作或更新操作,一般包括數據節點創建與刪除、數據節點內容更新和客戶端會話創建與失效等操作。對於每一個事務請求,Zookeeper 都會為其分配一個全局唯一的事務ID,用 ZXID 來表示,通常是一個 64 位的數字。每一個 ZXID 對應一次更新操作,從這些 ZXID 中可以間接地識別出 Zookeeper 處理這些更新操作請求的全局順序。
ZXID 是一個 64 位的數字,其中低 32 位可以看作是一個簡單的單調遞增的計數器,針對客戶端的每一個事務請求,Leader 伺服器在產生一個新的事務 Proposal 的時候,都會對該計數器進行加 1 操作;而高 32 位則代表了 Leader 周期 epoch 的編號,每當選舉產生一個新的 Leader 伺服器,就會從這個 Leader 伺服器上取出其本地日誌中最大事務 Proposal 的 ZXID,並從該 ZXID 中解析出對應的 epoch 值,然後再對其進行加 1 操作,之後就會以此編號作為新的 epoch,並將低 32 位置 0 來開始生成新的 ZXID。
Zookeeper 中為數據節點引入了版本的概念,每個數據節點都具有三種類型的版本信息(在上面的狀態信息中已經介紹了三種版本信息代表的意思),對數據節點的任何更新操作都會引起版本號的變化。其中我們以 dataVersion 為例來說明。在一個數據節點被創建完畢之後,節點的dataVersion 值是 0,表示的含義是 」當前節點自從創建之後,被更新過 0 次「。如果現在對該節點的數據內容進行更新操作,那麼隨後,dataVersion 的值就會變成 1。即表示的是對數據節點的數據內容的變更次數。
版本的作用是用來實現樂觀鎖機制中的 「寫入校驗」 的。例如,當要修改數據節點的數據內容時,帶上版本號,如果數據節點的版本號與傳入的版本號相等,就進行修改,否則修改失敗。
Zookeeper 提供了分布式數據的發布/訂閱功能。一個典型的發布/訂閱模型系統定義了一種一對多的訂閱關系,能夠讓多個訂閱者同時監聽某一個主題對象,當這個主題對象自身狀態變化時,會通知所有訂閱者,使它們能夠做出相應的處理。在 Zookeeper 中,引入了 Watcher 機制來實現這種分布式的通知功能。Zookeeper 允許客戶端向服務端注冊一個 Watcher 監聽,當服務端的一些指定事件觸發了這個 Watcher,那麼就會向指定客戶端發送一個事件通知來實現分布式的通知功能。
從上圖可以看出 Zookeeper 的 Watcher 機制主要包括客戶端線程、客戶端WatchMananger 和 Zookeeper 伺服器三部分。在具體工作流程上,簡單地講,客戶端在向 Zookeeper 伺服器注冊 Watcher 的同時,會將 Watcher 對象存儲在客戶端的 WatchMananger 中。當 Zookeeper 伺服器端觸發 Watcher 事件後,會向客戶端發送通知,客戶端線程從 WatchManager 中取出對應的 Watcher 對象來執行回調邏輯。
Watcher是一個介面,任何實現了Watcher介面的類就是一個新的Watcher。Watcher內部包含了兩個枚舉類:KeeperState、EventType
注 :客戶端接收到的相關事件通知中只包含狀態及類型等信息,不包括節點變化前後的具體內容,變化前的數據需業務自身存儲,變化後的數據需調用get等方法重新獲取;
上面講到zookeeper客戶端連接的狀態和zookeeper對znode節點監聽的事件類型,下面我們來講解如何建立zookeeper的watcher監聽。在zookeeper中採用zk.getChildren(path, watch)、zk.exists(path, watch)、zk.getData(path, watcher, stat)這樣的方式為某個znode注冊監聽。
下表以node-x節點為例,說明調用的注冊方法和可監聽事件間的關系:
Zookeeper 中提供了一套完善的 ACL(Access Control List)許可權控制機制來保障數據的安全。
ACL 由三部分組成,分別是:許可權模式(Scheme)、授權對象(ID)和許可權(Permission),通常使用「scheme: id:permission」來標識一個有效的ACL 信息。下面分別介紹:
1.7.4、ACL 超級管理員
zookeeper的許可權管理模式有一種叫做super,該模式提供一個超管可以方便的訪問任何許可權的節點
假設這個超管是:super:admin,需要先為超管生成密碼的密文
那麼打開zookeeper目錄下的/bin/zkServer.sh伺服器腳本文件,找到如下一行:
這就是腳本中啟動zookeeper的命令,默認只有以上兩個配置項,我們需要加一個超管的配置項
那麼修改以後這條完整命令變成了
之後啟動zookeeper,輸入如下命令添加許可權
在伺服器集群初始化階段,我們以 3 台機器組成的伺服器集群為例,當有一台伺服器server1 啟動的時候,它是無法進行 Leader 選舉的,當第二台機器 server2 也啟動時,此時這兩台伺服器已經能夠進行互相通信,每台機器都試圖找到一個 Leader,於是便進入了 Leader 選舉流程。
在zookeeper運行期間,leader與非leader伺服器各司其職,即便當有非leader伺服器宕機或新加入,此時也不會影響leader,但是一旦leader伺服器掛了,那麼整個集群將暫停對外服務,進入新一輪leader選舉,其過程和啟動時期的Leader選舉過程基本一致。
假設正在運行的有server1、server2、server3三台伺服器,當前leader是server2,若某一時刻leader掛了,此時便開始Leader選舉。選舉過程如下:
observer角色特點:
為了使用observer角色,在任何想變成observer角色的配置文件中加入如下配置:
並在所有server的配置文件中,配置成observer模式的server的那行配置追加:observer,例如:
G. Zookpeer是什麼在系統中如何起作用
Zookeeper分布式服務框架是Apache Hadoop的一個子項目,它主要是用來解決分布式應用中經常遇到的一些數據管理問題。如:統一命名服務、狀態同步服務、集群管理、分布式應用配置項的管理等。
我們先看看它都提供了哪些功能,然後再看看使用它的這些功能能做點什麼。
簡單的說,zookeeper=文件系統+通知機制。
Zookeeper維護一個類似文件系統的數據結構:
每個子目錄項如 NameService 都被稱作為 znode,和文件系統一樣,我們能夠自由的增加、刪除znode,在一個znode下增加、刪除子znode,唯一的不同在於znode是可以存儲數據的。
客戶端注冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、被刪除、子目錄節點增加刪除)時,zookeeper會通知客戶端。
這個似乎最簡單,在zookeeper的文件系統里創建一個目錄,即有唯一的path。在我們使用tborg無法確定上遊程序的部署機器時即可與下遊程序約定好path,通過path即能互相探索發現,不見不散了。
程序總是需要配置的,如果程序分散部署在多台機器上,要逐個改變配置就變得困難。
可以把這些配置全部放到zookeeper上去,保存在 Zookeeper 的某個目錄節點中,然後所有相關應用程序對這個目錄節點進行監聽,一旦配置信息發生變化,每個應用程序就會收到 Zookeeper 的通知,然後從 Zookeeper 獲取新的配置信息應用到系統中就好。
集群管理無在乎兩點:是否有機器退出和加入、選舉master。
對於第一點,所有機器約定在父目錄GroupMembers下創建臨時目錄節點,然後監聽父目錄節點的子節點變化消息。一旦有機器掛掉,該機器與 zookeeper的連接斷開,其所創建的臨時目錄節點被刪除,所有其他機器都收到通知:某個兄弟目錄被刪除,於是,所有人都知道:它下船了。當然又會有新機器加入,也是類似:所有機器收到通知---新兄弟目錄加入,highcount又有了,有人上船了。
對於第二點,我們假設機器創建臨時順序編號目錄節點,每次選取編號最小的機器作為master就好。
有了zookeeper的一致性文件系統,鎖的問題變得容易。鎖服務可以分為兩類,一個是保持獨占,另一個是控制時序。
對於第一類,我們將zookeeper上的一個znode看作是一把鎖,通過createznode的方式來實現。所有客戶端都去創建 /distribute_lock 節點,最終成功創建的那個客戶端也即擁有了這把鎖。廁所有言:來也沖沖,去也沖沖,用完刪除掉自己創建的distribute_lock 節點就釋放出鎖。
對於第二類, /distribute_lock 已經預先存在,所有客戶端在它下面創建臨時順序編號目錄節點,和選master一樣,編號最小的獲得鎖,用完刪除,依次方便。
兩種類型的隊列:
1、 同步隊列,當一個隊列的成員都聚齊時,這個隊列才可用,否則一直等待所有成員到達。
2、隊列按照 FIFO 方式進行入隊和出隊操作。
第一類,在約定目錄下創建臨時目錄節點,監聽節點數目是否是我們要求的數目。
第二類,和分布式鎖服務中的控制時序場景基本原理一致,入列有編號,出列按編號。
Zookeeper中的角色主要有以下三類:
系統模型如圖所示:
Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。Zab協議有兩種模式,它們分 別是恢復模式(選主)和廣播模式(同步)。當服務啟動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和 leader的狀態同步以後,恢復模式就結束了。狀態同步保證了leader和Server具有相同的系統狀態。
為了保證事務的順序一致性,zookeeper採用了遞增的事務id號(zxid)來標識事務。所有的提議(proposal)都在被提出的時候加上 了zxid。實現中zxid是一個64位的數字,它高32位是epoch用來標識leader關系是否改變,每次一個leader被選出來,它都會有一個 新的epoch,標識當前屬於那個leader的統治時期。低32位用於遞增計數。
每個Server在工作過程中有三種狀態:
當leader崩潰或者leader失去大多數的follower,這時候zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有的 Server都恢復到一個正確的狀態。Zk的選舉演算法有兩種:一種是基於basic paxos實現的,另外一種是基於fast paxos演算法實現的。系統默認的選舉演算法為fast paxos。先介紹basic paxos流程:
通過流程分析我們可以得出:要使Leader獲得多數Server的支持,則Server總數必須是奇數2n+1,且存活的Server的數目不得少於n+1.
選完leader以後,zk就進入狀態同步過程。
Leader主要有三個功能:
PING消息是指Learner的心跳信息;REQUEST消息是Follower發送的提議信息,包括寫請求及同步請求;ACK消息是 Follower的對提議的回復,超過半數的Follower通過,則commit該提議;REVALIDATE消息是用來延長SESSION有效時間。
Leader的工作流程簡圖如下所示,在實際實現中,流程要比下圖復雜得多,啟動了三個線程來實現功能。
Follower主要有四個功能:
Follower的消息循環處理如下幾種來自Leader的消息:
Follower的工作流程簡圖如下所示,在實際實現中,Follower是通過5個線程來實現功能的。
https://blog.csdn.net/xinguan1267/article/details/38422149
https://blog.csdn.net/gs80140/article/details/51496925
https://www.2cto.com/kf/201708/668587.html
https://blog.csdn.net/milhua/article/details/78931672
P.S. 這篇文章是本人對網路上關於ZK的文章閱讀之後整理所得,作為入門級的了解。個人覺得看了上面的內容就能基本了解Zookeeper的作用了,後面在結合實際項目使用加深自己的了解。
end