天天看點

為什麼Eureka比ZooKeeper更适合做服務發現?

Eureka的優勢

1、在Eureka平台中,如果某台伺服器當機,Eureka不會有類似于ZooKeeper的選舉leader的過程;用戶端請求會自動切換到新的Eureka節點;當當機的伺服器重新恢複後,Eureka會再次将其納入到伺服器叢集管理之中;而對于它來說,所有要做的無非是同步一些新的服務注冊資訊而已。是以,再也不用擔心有“掉隊”的伺服器恢複以後,會從Eureka伺服器叢集中剔除出去的風險了。Eureka甚至被設計用來應付範圍更廣的網絡分割故障,并實作“0”當機維護需求。(多個zookeeper之間網絡出現問題,造成出現多個leader,發生腦裂)當網絡分割故障發生時,每個Eureka節點,會持續的對外提供服務(注:ZooKeeper不會):接收新的服務注冊同時将它們提供給下遊的服務發現請求。這樣一來,就可以實作在同一個子網中(same side of partition),新釋出的服務仍然可以被發現與通路。

2、正常配置下,Eureka内置了心跳服務,用于淘汰一些“瀕死”的伺服器;如果在Eureka中注冊的服務,它的“心跳”變得遲緩時,Eureka會将其整個剔除出管理範圍(這點有點像ZooKeeper的做法)。這是個很好的功能,但是當網絡分割故障發生時,這也是非常危險的;因為,那些因為網絡問題(注:心跳慢被剔除了)而被剔除出去的伺服器本身是很”健康“的,隻是因為網絡分割故障把Eureka叢集分割成了獨立的子網而不能互訪而已。

幸運的是,Netflix考慮到了這個缺陷。如果Eureka服務節點在短時間裡丢失了大量的心跳連接配接(注:可能發生了網絡故障),那麼這個Eureka節點會進入”自我保護模式“,同時保留那些“心跳死亡“的服務注冊資訊不過期。此時,這個Eureka節點對于新的服務還能提供注冊服務,對于”死亡“的仍然保留,以防還有用戶端向其發起請求。當網絡故障恢複後,這個Eureka節點會退出”自我保護模式“。是以Eureka的哲學是,同時保留”好資料“與”壞資料“總比丢掉任何”好資料“要更好,是以這種模式在實踐中非常有效。

3、Eureka還有用戶端緩存功能(注:Eureka分為用戶端程式與伺服器端程式兩個部分,用戶端程式負責向外提供注冊與發現服務接口)。是以即便Eureka叢集中所有節點都失效,或者發生網絡分割故障導緻用戶端不能通路任何一台Eureka伺服器;Eureka服務的消費者仍然可以通過Eureka用戶端緩存來擷取現有的服務注冊資訊。甚至最極端的環境下,所有正常的Eureka節點都不對請求産生相應,也沒有更好的伺服器解決方案來解決這種問題

時;得益于Eureka的用戶端緩存技術,消費者服務仍然可以通過Eureka用戶端查詢與擷取注冊服務資訊,這點很重要。

4、Eureka的構架保證了它能夠成為Service發現服務。它相對與ZooKeeper來說剔除了Leader節點的選取或者事務日志機制,這樣做有利于減少使用者維護的難度也保證了Eureka的在運作時的健壯性。而且Eureka就是為發現服務所設計的,它有獨立的用戶端程式庫,同時提供心跳服務、服務健康監測、自動釋出服務與自動重新整理緩存的功能。但是,如果使用ZooKeeper你必須自己來實作這些功能。Eureka的所有庫都是開源的,所有人都能看到與使用這些源代碼,這比那些隻有一兩個人能看或者維護的用戶端庫要好。

5、維護Eureka伺服器也非常的簡單,比如,切換一個節點隻需要在現有EIP下移除一個現有的節點然後添加一個新的就行。Eureka提供了一個web-based的圖形化的運維界面,在這個界面中可以檢視Eureka所管理的注冊服務的運作狀态資訊:是否健康,運作日志等。Eureka甚至提供了Restful-API接口,友善第三方程式內建Eureka的功能。

ZooKeeper的劣勢

   在分布式系統領域有個著名的CAP定理(C-資料一緻性;A-服務可用性;P-服務對網絡分區故障的容錯性,這三個特性在任何分布式系統中不能同時滿足,最多同時滿足兩個);ZooKeeper是個CP的,即任何時刻對ZooKeeper的通路請求能得到一緻的資料結果,同時系統對網絡分割具備容錯性;但是它不能保證每次服務請求的可用性(注:也就是在極端環境下,ZooKeeper可能會丢棄一些請求,消費者程式需要重新請求才能獲得結果)。但是别忘了,ZooKeeper是分布式協調服務,它的職責是保證資料(注:配置資料,狀态資料)在其管轄下的所有服務之間保持同步、一緻;是以就不難了解為什麼ZooKeeper被設計成CP而不是AP特性的了,如果是AP的,那麼将會帶來恐怖的後果(注:ZooKeeper就像交叉路口的信号燈一樣,你能想象在交通要道突然信号燈失靈的情況嗎?)。而且,作為ZooKeeper的核心實作算法Zab,就是解決了分布式系統下資料如何在多個服務之間保持同步問題的。

1、對于Service發現服務來說就算是傳回了包含不實的資訊的結果也比什麼都不傳回要好;再者,對于Service發現服務而言,甯可傳回某服務5分鐘之前在哪幾個伺服器上可用的資訊,也不能因為暫時的網絡故障而找不到可用的伺服器,而不傳回任何結果。是以說,用ZooKeeper來做Service發現服務是肯定錯誤的,如果你這麼用就慘了!

   如果被用作Service發現服務,ZooKeeper本身并沒有正确的處理網絡分割的問題;而在雲端,網絡分割問題跟其他類型的故障一樣的确會發生;是以最好提前對這個問題做好100%的準備。就像Jepsen在ZooKeeper網站上釋出的部落格中所說:在ZooKeeper中,如果在同一個網絡分區(partition)的節點數(nodes)數達不到ZooKeeper選取Leader節點的“法定人數”時,它們就會從ZooKeeper中斷開,當然同時也就不能提供Service發現服務了。

2、ZooKeeper下所有節點不可能保證任何時候都能緩存所有的服務注冊資訊。如果ZooKeeper下所有節點都斷開了,或者叢集中出現了網絡分割的故障(注:由于交換機故障導緻交換機底下的子網間不能互訪);那麼ZooKeeper會将它們都從自己管理範圍中剔除出去,外界就不能通路到這些節點了,即便這些節點本身是“健康”的,可以正常提供服務的;是以導緻到達這些節點的服務請求被丢失了。(注:這也是為什麼ZooKeeper不滿足CAP中A的原因)

3、更深層次的原因是,ZooKeeper是按照CP原則建構的,也就是說它能保證每個節點的資料保持一緻,而為ZooKeeper加上緩存的做法的目的是為了讓ZooKeeper變得更加可靠(available);但是,ZooKeeper設計的本意是保持節點的資料一緻,也就是CP。是以,這樣一來,你可能既得不到一個資料一緻的(CP)也得不到一個高可用的(AP)的Service發現服務了;因為,這相當于你在一個已有的CP系統上強制栓了一個AP的系統,這在本質上就行不通的!一個Service發現服務應該從一開始就被設計成高可用的才行!

4、如果抛開CAP原理不管,正确的設定與維護ZooKeeper服務就非常的困難;錯誤會經常發生,導緻很多工程被建立隻是為了減輕維護ZooKeeper的難度。這些錯誤不僅存在與用戶端而且還存在于ZooKeeper伺服器本身。Knewton平台很多故障就是由于ZooKeeper使用不當而導緻的。那些看似簡單的操作,如:正确的重建觀察者(reestablishing watcher)、用戶端Session與異常的處理與在ZK視窗中管理記憶體都是非常容易導緻ZooKeeper出錯的。同時,我們确實也遇到過ZooKeeper的一些經典bug:ZooKeeper-1159 與ZooKeeper-1576;我們甚至在生産環境中遇到過ZooKeeper選舉Leader節點失敗的情況。這些問題之是以會出現,在于ZooKeeper需要管理與保障所管轄服務群的Session與網絡連接配接資源(注:這些資源的管理在分布式系統環境下是極其困難的);但是它不負責管理服務的發現,是以使用ZooKeeper當Service發現服務得不償失。

一個叢集有3台機器,挂了一台後的影響是什麼?挂了兩台呢? 

挂了一台:挂了一台後就是收不到其中一台的投票,但是有兩台可以參與投票,按照上面的邏輯,它們開始都投給自己,後來按照選舉的原則,兩個人都投票給其中一個,那麼就有一個節點獲得的票等于2,2 > (3/2)=1 的,超過了半數,這個時候是能選出leader的。

挂了兩台: 挂了兩台後,怎麼弄也隻能獲得一張票, 1 不大于 (3/2)=1的,這樣就無法選出一個leader了。

ZooKeeper為高可用的一緻性協調架構,自然的ZooKeeper也有着一緻性算法的實作,ZooKeeper使用的是ZAB協定作為資料一緻性的算法, ZAB(ZooKeeper Atomic Broadcast ) 全稱為:原子消息廣播協定;ZAB可以說是在Paxos算法基礎上進行了擴充改造而來的,ZAB協定設計了支援崩潰恢複,ZooKeeper使用單一主程序Leader用于處理用戶端所有事務請求,采用ZAB協定将伺服器數狀态以事務形式廣播到所有Follower上;由于事務間可能存在着依賴關系,ZAB協定保證Leader廣播的變更序列被順序的處理,:一個狀态被處理那麼它所依賴的狀态也已經提前被處理;ZAB協定支援的崩潰恢複可以保證在Leader程序崩潰的時候可以重新選出Leader并且保證資料的完整性;

在ZooKeeper中所有的事務請求都由一個主伺服器也就是Leader來處理,其他伺服器為Follower,Leader将用戶端的事務請求轉換為事務Proposal,并且将Proposal分發給叢集中其他所有的Follower,然後Leader等待Follwer回報,當有 過半數(>=N/2+1) 的Follower回報資訊後,Leader将再次向叢集内Follower廣播Commit資訊,Commit為将之前的Proposal送出;

http://www.cnblogs.com/yuyijq/p/4116365.html

http://blog.csdn.net/u010185262/article/details/49910301

http://www.tuicool.com/articles/IfQR3u3

http://www.cnblogs.com/rainy-shurun/p/5414110.html

http://dockone.io/article/78

繼續閱讀