天天看點

CAP理論與Nacos,Eureka,Zookerper之間的聯系

微服務中的CAP理論

CAP原則又稱CAP定理,指的是在一個分布式系統中,一緻性(Consistency)、可用性(Availability)、分區容錯(Partition-tolerance)。在一個分布式系統中三個要素不可同時具有,隻能選擇其中兩個。

CAP理論與Nacos,Eureka,Zookerper之間的聯系

一緻性(Consistency)

在分布式系統中,所有節點在同一時刻的資料都是一緻的。

可用性(Availability)

在叢集中一部分節點故障後,叢集整體是否還能響應用戶端的讀寫請求。即每個請求不管成功與否都能得到響應。

分區容錯(Partition-tolerance)

保證系統中任意資訊的丢失都不會影響系統的運作。

一個分布式系統裡面,節點組成的網絡本來應該是連通的。然而可能因為一些故障,使得有些節點之間不連通了,整個網絡就分成了幾塊區域。資料就散布在了這些不連通的區域中。這就叫分區。

AP

保持可用性和分區容錯。如果選擇分區容錯性和可用性,當節點損壞時,遇到分區事件,受影響的服務不需要等待資料一緻,就可以對外提供服務,保證了可用性就必須放棄一緻性。

CP

保證一緻性和分區容錯。如果選擇分區容錯性和一緻性,為保證一緻性,各個節點之間的資料必須保持一緻,當出現分區時,會導緻同步時間無限延長,在同步的這段時間就無法對外提供服務,就無法保證可用性。

CA

保持一緻性的同時保證可用性,這在分布式系統中是不存在的,因為分區問題總是會出現在分布式系統中。出現分區就必然會産生一緻性問題和可用性問題,一緻性和可用性兩者隻能選其一。

Apache Zookeeper -> CP

與 Eureka 有所不同,Apache Zookeeper 在設計時就緊遵CP原則,即任何時候對 Zookeeper 的通路請求能得到一緻的資料結果,同時系統對網絡分割具備容錯性,但是 Zookeeper 不能保證每次服務請求都是可達的。

從 Zookeeper 的實際應用情況來看,在使用 Zookeeper 擷取服務清單時,如果此時的 Zookeeper 叢集中的 Leader 當機了,該叢集就要進行 Leader 的選舉,又或者 Zookeeper 叢集中半數以上伺服器節點不可用(例如有三個節點,如果節點一檢測到節點三挂了 ,節點二也檢測到節點三挂了,那這個節點才算是真的挂了),那麼将無法處理該請求。是以說,Zookeeper 不能保證服務可用性。

當然,在大多數分布式環境中,尤其是涉及到資料存儲的場景,資料一緻性應該是首先被保證的,這也是 Zookeeper 設計緊遵CP原則的另一個原因。

但是對于服務發現來說,情況就不太一樣了,針對同一個服務,即使注冊中心的不同節點儲存的服務提供者資訊不盡相同,也并不會造成災難性的後果。

因為對于服務消費者來說,能消費才是最重要的,消費者雖然拿到可能不正确的服務執行個體資訊後嘗試消費一下,也要勝過因為無法擷取執行個體資訊而不去消費,導緻系統異常要好(淘寶的雙十一,京東的618就是緊遵AP的最好參照)。

當master節點因為網絡故障與其他節點失去聯系時,剩餘節點會重新進行leader選舉。問題在于,選舉leader的時間太長,30~120s,而且選舉期間整個zk叢集都是不可用的,這就導緻在選舉期間注冊服務癱瘓。

在雲部署環境下, 因為網絡問題使得zk叢集失去master節點是大機率事件,雖然服務能最終恢複,但是漫長的選舉事件導緻注冊長期不可用是不能容忍的。

Spring Cloud Eureka -> AP

Spring Cloud Netflix 在設計 Eureka 時就緊遵AP原則(盡管現在2.0釋出了,但是由于其閉源的原因 ,但是目前 Ereka 1.x 任然是比較活躍的)。

Eureka Server 也可以運作多個執行個體來建構叢集,解決單點問題,但不同于 ZooKeeper 的選舉 leader 的過程,Eureka Server 采用的是Peer to Peer 對等通信。這是一種去中心化的架構,無 master/slave 之分,每一個 Peer 都是對等的。在這種架構風格中,節點通過彼此互相注冊來提高可用性,每個節點需要添加一個或多個有效的 serviceUrl 指向其他節點。每個節點都可被視為其他節點的副本。

在叢集環境中如果某台 Eureka Server 當機,Eureka Client 的請求會自動切換到新的 Eureka Server 節點上,當當機的伺服器重新恢複後,Eureka 會再次将其納入到伺服器叢集管理之中。當節點開始接受用戶端請求時,所有的操作都會在節點間進行複制(replicate To Peer)操作,将請求複制到該 Eureka Server 目前所知的其它所有節點中。

當一個新的 Eureka Server 節點啟動後,會首先嘗試從鄰近節點擷取所有注冊清單資訊,并完成初始化。Eureka Server 通過 getEurekaServiceUrls() 方法擷取所有的節點,并且會通過心跳契約的方式定期更新。

預設情況下,如果 Eureka Server 在一定時間内沒有接收到某個服務執行個體的心跳(預設周期為30秒),Eureka Server 将會登出該執行個體(預設為90秒, eureka.instance.lease-expiration-duration-in-seconds 進行自定義配置)。

當 Eureka Server 節點在短時間内丢失過多的心跳時,那麼這個節點就會進入自我保護模式。

Eureka的叢集中,隻要有一台Eureka還在,就能保證注冊服務可用(保證可用性),隻不過查到的資訊可能不是最新的(不保證強一緻性)。除此之外,Eureka還有一種自我保護機制,如果在15分鐘内超過85%的節點都沒有正常的心跳,那麼Eureka就認為用戶端與注冊中心出現了網絡故障,此時會出現以下幾種情況:

  1. Eureka不再從系統資料庫中移除因為長時間沒有收到心跳而過期的服務;
  1. Eureka仍然能夠接受新服務注冊和查詢請求,但是不會被同步到其它節點上(即保證目前節點依然可用);
  1. 當網絡穩定時,目前執行個體新注冊的資訊會被同步到其它節點中;

是以,Eureka可以很好的應對因網絡故障導緻部分節點失去聯系的情況,而不會像zookeeper那樣使得整個注冊服務癱瘓。

Nacos

Nacos預設采用AP模式,在1.0版本之後采用ap+cp模式混合實作。

Nacos是阿裡開源的,Nacos 支援基于 DNS 和基于 RPC 的服務發現。在Spring Cloud中使用Nacos,隻需要先下載下傳 Nacos 并啟動 Nacos server,Nacos隻需要簡單的配置就可以完成服務的注冊發現。

Nacos除了服務的注冊發現之外,還支援動态配置服務。動态配置服務可以讓您以中心化、外部化和動态化的方式管理所有環境的應用配置和服務配置。動态配置消除了配置變更時重新部署應用和服務的需要,讓配置管理變得更加高效和靈活。配置中心化管理讓實作無狀态服務變得更簡單,讓服務按需彈性擴充變得更容易。

一句話概括就是Nacos = Spring Cloud注冊中心 + Spring Cloud配置中心。