天天看點

ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?

文章目錄

  • ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?
    • 前言
    • CAP理論
    • 服務注冊中心解決方案
    • 主流注冊中心産品
    • Apache Zookeeper → CP
    • Spring Cloud Eureka → AP
    • Consul → CP
      • Consul Template
    • Nacos

ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?

ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?

前言

服務注冊中心本質上是為了解耦服務提供者和服務消費者。對于任何一個微服務,原則上都應存在或者支援多個提供者,這是由微服務的分布式屬性決定的。更進一步,為了支援彈性擴縮容特性,一個微服務的提供者的數量和分布往往是動态變化的,也是無法預先确定的。是以,原本在單體應用階段常用的靜态 LB 機制就不再适用了,需要引入額外的元件來管理微服務提供者的注冊與發現,而這個元件就是服務注冊中心。

CAP理論

CAP 理論是分布式架構中重要理論

  • 一緻性 (Consistency) 所有節點在同一時間具有相同的資料
  • 可用性 (Availability) 保證每個請求不管成功或者失敗都有響應
  • 分隔容忍 (Partition tolerance) 系統中任意資訊的丢失或失敗不會影響系統的繼續運作

關于 P 的了解,我覺得是在整個系統中某個部分,挂掉了,或者當機了,并不影響整個系統的運作或者說使用,而可用性是,某個系統的某個節點挂了,但是并不影響系統的接受或者送出請求,CAP 不可能都滿足,隻能取其中 2 個原因是如果 C 是第一需求的話,那麼會影響 A 的性能,因為要資料同步,不然請求結果會有差異,但是資料同步會消耗時間,期間可用性就會降低。

如果 A 是第一需求,那麼隻要有一個服務在,就能正常接受請求,但是對與傳回結果就不能保證資料一緻性,原因是,在分布式部署的時候,資料一緻的過程不可能想切線路那麼快。

再如果,同時滿足一緻性和可用性,那麼分區容錯就很難保證了,也就是單點,也是分布式的基本核心,好了,明白這些理論,就可以在相應的場景選取服務注冊與發現了

服務注冊中心解決方案

設計或者選型一個服務注冊中心,首先要考慮的就是服務注冊與發現機制。縱觀當下各種主流的服務注冊中心解決方案,大緻可歸為三類:

  • 應用内:直接內建到應用中,依賴于應用自身完成服務的注冊與發現,最典型的是 Netflix 提供的 Eureka
  • 應用外:把應用當成黑盒,通過應用外的某種機制将服務注冊到注冊中心,最小化對應用的侵入性,比如 Airbnb 的 SmartStack,HashiCorp 的 Consul
  • DNS:将服務注冊為 DNS 的 SRV 記錄,嚴格來說,是一種特殊的應用外注冊方式,SkyDNS 是其中的代表
注 1: 對于第一類注冊方式,除了 Eureka 這種一站式解決方案,還可以基于 ZooKeeper 或者 Etcd 自行實作一套服務注冊機制,這在大公司比較常見,但對于小公司而言顯然成本效益太低。
注 2: 由于 DNS 固有的緩存缺陷,本文不對第三類注冊方式作深入探讨。

除了基本的服務注冊與發現機制,從開發和運維角度,至少還要考慮如下五個方面:

  • 測活:服務注冊之後,如何對服務進行測活以保證服務的可用性?
  • 負載均衡:當存在多個服務提供者時,如何均衡各個提供者的負載?
  • 內建:在服務提供端或者調用端,如何內建注冊中心?
  • 運作時依賴:引入注冊中心之後,對應用的運作時環境有何影響?
  • 可用性:如何保證注冊中心本身的可用性,特别是消除單點故障?

主流注冊中心産品

軟體産品特性并非一成不變,如果發現功能特性有變更,歡迎評論指正
ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?

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

ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?

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

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

Consul → CP

Consul 是 HashiCorp 公司推出的開源工具,用于實作分布式系統的服務發現與配置。Consul 使用 Go 語言編寫,是以具有天然可移植性(支援 Linux、windows 和 Mac OS X)。

Consul 内置了服務注冊與發現架構、分布一緻性協定實作、健康檢查、Key/Value 存儲、多資料中心方案,不再需要依賴其他工具(比如 ZooKeeper 等),使用起來也較為簡單。

Consul 遵循 CAP 原理中的 CP 原則,保證了強一緻性和分區容錯性,且使用的是 Raft 算法,比 zookeeper 使用的 Paxos 算法更加簡單。雖然保證了強一緻性,但是可用性就相應下降了,例如服務注冊的時間會稍長一些,因為 Consul 的 raft 協定要求必須過半數的節點都寫入成功才認為注冊成功 ;在 leader 挂掉了之後,重新選舉出 leader 之前會導緻 Consul 服務不可用。

ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?

Consul 本質上屬于應用外的注冊方式,但可以通過 SDK 簡化注冊流程。而服務發現恰好相反,預設依賴于 SDK,但可以通過 Consul Template(下文會提到)去除 SDK 依賴。

ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?ZooKeeper、Eureka、Consul 、Nacos,微服務注冊中心怎麼選?

Consul Template

Consul,預設服務調用者需要依賴 Consul SDK 來發現服務,這就無法保證對應用的零侵入性。

所幸通過 Consul Template,可以定時從 Consul 叢集擷取最新的服務提供者清單并重新整理 LB 配置(比如 nginx 的 upstream),這樣對于服務調用者而言,隻需要配置一個統一的服務調用位址即可。

Consul 強一緻性 © 帶來的是:

  • 服務注冊相比 Eureka 會稍慢一些。因為 Consul 的 raft 協定要求必須過半數的節點都寫入成功才認為注冊成功
  • Leader 挂掉時,重新選舉期間整個 consul 不可用。保證了強一緻性但犧牲了可用性。

Eureka 保證高可用 (A) 和最終一緻性:

  • 服務注冊相對要快,因為不需要等注冊資訊 replicate(複制) 到其他節點,也不保證注冊資訊是否 replicate 成功
  • 當資料出現不一緻時,雖然 A, B 上的注冊資訊不完全相同,但每個 Eureka 節點依然能夠正常對外提供服務,這會出現查詢服務資訊時如果請求 A 查不到,但請求 B 就能查到。如此保證了可用性但犧牲了一緻性。

其他方面,eureka 就是個 servlet 程式,跑在 servlet 容器中; Consul 則是 go 編寫而成。

Nacos

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

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

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

轉載:https://mp.weixin.qq.com/s/qUb3F42LO8dk2zja3prFyQ

繼續閱讀