ZooKeeper、Eureka、Consul、Nacos,怎么選?
圖片來自 Pexels
更進(jìn)一步,為了支持彈性擴(kuò)縮容特性,一個(gè)微服務(wù)的提供者的數(shù)量和分布往往是動(dòng)態(tài)變化的,也是無法預(yù)先確定的。
因此,原本在單體應(yīng)用階段常用的靜態(tài) LB 機(jī)制就不再適用了,需要引入額外的組件來管理微服務(wù)提供者的注冊(cè)與發(fā)現(xiàn),而這個(gè)組件就是服務(wù)注冊(cè)中心。
CAP 理論
CAP 理論是分布式架構(gòu)中重要理論:
- 一致性(Consistency),所有節(jié)點(diǎn)在同一時(shí)間具有相同的數(shù)據(jù)。
- 可用性(Availability),保證每個(gè)請(qǐng)求不管成功或者失敗都有響應(yīng)。
- 分隔容忍(Partition tolerance),系統(tǒng)中任意信息的丟失或失敗不會(huì)影響系統(tǒng)的繼續(xù)運(yùn)作。
關(guān)于 P 的理解,我覺得是在整個(gè)系統(tǒng)中某個(gè)部分,掛掉了,或者宕機(jī)了,并不影響整個(gè)系統(tǒng)的運(yùn)作或者說使用,而可用性是,某個(gè)系統(tǒng)的某個(gè)節(jié)點(diǎn)掛了,但是并不影響系統(tǒng)的接受或者發(fā)出請(qǐng)求,CAP 不可能都取,只能取其中 2 個(gè)。
原因是如果 C 是第一需求的話,那么會(huì)影響 A 的性能,因?yàn)橐獢?shù)據(jù)同步,不然請(qǐng)求結(jié)果會(huì)有差異,但是數(shù)據(jù)同步會(huì)消耗時(shí)間,期間可用性就會(huì)降低。
如果 A 是第一需求,那么只要有一個(gè)服務(wù)在,就能正常接受請(qǐng)求,但是對(duì)與返回結(jié)果變不能保證,原因是,在分布式部署的時(shí)候,數(shù)據(jù)一致的過程不可能想切線路那么快。
再如果,同時(shí)滿足一致性和可用性,那么分區(qū)容錯(cuò)就很難保證了,也就是單點(diǎn),也是分布式的基本核心,好了,明白這些理論,就可以在相應(yīng)的場(chǎng)景選取服務(wù)注冊(cè)與發(fā)現(xiàn)了。
服務(wù)注冊(cè)中心解決方案
設(shè)計(jì)或者選型一個(gè)服務(wù)注冊(cè)中心,首先要考慮的就是服務(wù)注冊(cè)與發(fā)現(xiàn)機(jī)制。
縱觀當(dāng)下各種主流的服務(wù)注冊(cè)中心解決方案,大致可歸為三類:
- 應(yīng)用內(nèi):直接集成到應(yīng)用中,依賴于應(yīng)用自身完成服務(wù)的注冊(cè)與發(fā)現(xiàn),最典型的是 Netflix 提供的 Eureka。
- 應(yīng)用外:把應(yīng)用當(dāng)成黑盒,通過應(yīng)用外的某種機(jī)制將服務(wù)注冊(cè)到注冊(cè)中心,最小化對(duì)應(yīng)用的侵入性,比如 Airbnb 的 SmartStack,HashiCorp 的 Consul。
- DNS:將服務(wù)注冊(cè)為 DNS 的 SRV 記錄,嚴(yán)格來說,是一種特殊的應(yīng)用外注冊(cè)方式,SkyDNS 是其中的代表。
注 1:對(duì)于第一類注冊(cè)方式,除了 Eureka 這種一站式解決方案,還可以基于 ZooKeeper 或者 etcd 自行實(shí)現(xiàn)一套服務(wù)注冊(cè)機(jī)制,這在大公司比較常見,但對(duì)于小公司而言顯然性價(jià)比太低。
注 2:由于 DNS 固有的緩存缺陷,本文不對(duì)第三類注冊(cè)方式作深入探討。
除了基本的服務(wù)注冊(cè)與發(fā)現(xiàn)機(jī)制,從開發(fā)和運(yùn)維角度,至少還要考慮如下五個(gè)方面:
- 測(cè)活:服務(wù)注冊(cè)之后,如何對(duì)服務(wù)進(jìn)行測(cè)活以保證服務(wù)的可用性?
- 負(fù)載均衡:當(dāng)存在多個(gè)服務(wù)提供者時(shí),如何均衡各個(gè)提供者的負(fù)載?
- 集成:在服務(wù)提供端或者調(diào)用端,如何集成注冊(cè)中心?
- 運(yùn)行時(shí)依賴:引入注冊(cè)中心之后,對(duì)應(yīng)用的運(yùn)行時(shí)環(huán)境有何影響?
- 可用性:如何保證注冊(cè)中心本身的可用性,特別是消除單點(diǎn)故障?
主流注冊(cè)中心產(chǎn)品
軟件產(chǎn)品特性并非一成不變,如果發(fā)現(xiàn)功能特性有變更,歡迎評(píng)論指正:
- Consul 是支持自動(dòng)注銷服務(wù)實(shí)例,在 check 的 DeregisterCriticalServiceAfter 這個(gè)參數(shù)。
- 新版本的 Dubbo 也擴(kuò)展了對(duì) Consul 的支持。
①Apache Zookeeper→CP
與 Eureka 有所不同,Apache ZooKeeper 在設(shè)計(jì)時(shí)就緊遵 CP 原則,即任何時(shí)候?qū)?ZooKeeper 的訪問請(qǐng)求能得到一致的數(shù)據(jù)結(jié)果,同時(shí)系統(tǒng)對(duì)網(wǎng)絡(luò)分割具備容錯(cuò)性,但是 ZooKeeper 不能保證每次服務(wù)請(qǐng)求都是可達(dá)的。
從 ZooKeeper 的實(shí)際應(yīng)用情況來看,在使用 ZooKeeper 獲取服務(wù)列表時(shí),如果此時(shí)的 ZooKeeper 集群中的 Leader 宕機(jī)了,該集群就要進(jìn)行 Leader 的選舉。
又或者 ZooKeeper 集群中半數(shù)以上服務(wù)器節(jié)點(diǎn)不可用(例如有三個(gè)節(jié)點(diǎn),如果節(jié)點(diǎn)一檢測(cè)到節(jié)點(diǎn)三掛了 ,節(jié)點(diǎn)二也檢測(cè)到節(jié)點(diǎn)三掛了,那這個(gè)節(jié)點(diǎn)才算是真的掛了),那么將無法處理該請(qǐng)求。
所以說,ZooKeeper 不能保證服務(wù)可用性。當(dāng)然,在大多數(shù)分布式環(huán)境中,尤其是涉及到數(shù)據(jù)存儲(chǔ)的場(chǎng)景,數(shù)據(jù)一致性應(yīng)該是首先被保證的,這也是 ZooKeeper 設(shè)計(jì)緊遵 CP 原則的另一個(gè)原因。
但是對(duì)于服務(wù)發(fā)現(xiàn)來說,情況就不太一樣了,針對(duì)同一個(gè)服務(wù),即使注冊(cè)中心的不同節(jié)點(diǎn)保存的服務(wù)提供者信息不盡相同,也并不會(huì)造成災(zāi)難性的后果。
因?yàn)閷?duì)于服務(wù)消費(fèi)者來說,能消費(fèi)才是最重要的,消費(fèi)者雖然拿到可能不正確的服務(wù)實(shí)例信息后嘗試消費(fèi)一下,也要?jiǎng)龠^因?yàn)闊o法獲取實(shí)例信息而不去消費(fèi),導(dǎo)致系統(tǒng)異常要好(淘寶的雙十一,京東的 618 就是緊遵 AP 的最好參照)。
當(dāng) Master 節(jié)點(diǎn)因?yàn)榫W(wǎng)絡(luò)故障與其他節(jié)點(diǎn)失去聯(lián)系時(shí),剩余節(jié)點(diǎn)會(huì)重新進(jìn)行 Leader 選舉。
問題在于,選舉 Leader 的時(shí)間太長(zhǎng),30~120s,而且選舉期間整個(gè) ZooKeeper 集群都是不可用的,這就導(dǎo)致在選舉期間注冊(cè)服務(wù)癱瘓。
在云部署環(huán)境下, 因?yàn)榫W(wǎng)絡(luò)問題使得 ZooKeeper 集群失去 Master 節(jié)點(diǎn)是大概率事件,雖然服務(wù)能最終恢復(fù),但是漫長(zhǎng)的選舉事件導(dǎo)致注冊(cè)長(zhǎng)期不可用是不能容忍的。
②Spring Cloud Eureka→AP
Spring Cloud Netflix 在設(shè)計(jì) Eureka 時(shí)就緊遵 AP 原則(盡管現(xiàn)在 2.0 發(fā)布了,但是由于其閉源的原因 ,但是目前 Ereka 1.x 任然是比較活躍的)。
Eureka Server 也可以運(yùn)行多個(gè)實(shí)例來構(gòu)建集群,解決單點(diǎn)問題,但不同于 ZooKeeper 的選舉 Leader 的過程,Eureka Server 采用的是 Peer to Peer 對(duì)等通信。
這是一種去中心化的架構(gòu),無 Master/Slave 之分,每一個(gè) Peer 都是對(duì)等的。
在這種架構(gòu)風(fēng)格中,節(jié)點(diǎn)通過彼此互相注冊(cè)來提高可用性,每個(gè)節(jié)點(diǎn)需要添加一個(gè)或多個(gè)有效的 serviceUrl 指向其他節(jié)點(diǎn)。每個(gè)節(jié)點(diǎn)都可被視為其他節(jié)點(diǎn)的副本。
在集群環(huán)境中如果某臺(tái) Eureka Server 宕機(jī),Eureka Client 的請(qǐng)求會(huì)自動(dòng)切換到新的 Eureka Server 節(jié)點(diǎn)上,當(dāng)宕機(jī)的服務(wù)器重新恢復(fù)后,Eureka 會(huì)再次將其納入到服務(wù)器集群管理之中。
當(dāng)節(jié)點(diǎn)開始接受客戶端請(qǐng)求時(shí),所有的操作都會(huì)在節(jié)點(diǎn)間進(jìn)行復(fù)制(replicate To Peer)操作,將請(qǐng)求復(fù)制到該Eureka Server當(dāng)前所知的其它所有節(jié)點(diǎn)中。
當(dāng)一個(gè)新的 Eureka Server 節(jié)點(diǎn)啟動(dòng)后,會(huì)首先嘗試從鄰近節(jié)點(diǎn)獲取所有注冊(cè)列表信息,并完成初始化。
Eureka Server 通過 getEurekaServiceUrls() 方法獲取所有的節(jié)點(diǎn),并且會(huì)通過心跳契約的方式定期更新。
默認(rèn)情況下,如果 Eureka Server 在一定時(shí)間內(nèi)沒有接收到某個(gè)服務(wù)實(shí)例的心跳(默認(rèn)周期為 30 秒)。
Eureka Server 將會(huì)注銷該實(shí)例(默認(rèn)為 90 秒,eureka.instance.lease-expiration-duration-in-seconds 進(jìn)行自定義配置)。
當(dāng) Eureka Server 節(jié)點(diǎn)在短時(shí)間內(nèi)丟失過多的心跳時(shí),那么這個(gè)節(jié)點(diǎn)就會(huì)進(jìn)入自我保護(hù)模式。
Eureka 的集群中,只要有一臺(tái) Eureka 還在,就能保證注冊(cè)服務(wù)可用(保證可用性),只不過查到的信息可能不是最新的(不保證強(qiáng)一致性)。
除此之外,Eureka 還有一種自我保護(hù)機(jī)制,如果在 15 分鐘內(nèi)超過 85% 的節(jié)點(diǎn)都沒有正常的心跳,那么 Eureka 就認(rèn)為客戶端與注冊(cè)中心出現(xiàn)了網(wǎng)絡(luò)故障。
此時(shí)會(huì)出現(xiàn)以下幾種情況:
- Eureka 不再從注冊(cè)表中移除因?yàn)殚L(zhǎng)時(shí)間沒有收到心跳而過期的服務(wù)。
- Eureka 仍然能夠接受新服務(wù)注冊(cè)和查詢請(qǐng)求,但是不會(huì)被同步到其它節(jié)點(diǎn)上(即保證當(dāng)前節(jié)點(diǎn)依然可用)。
- 當(dāng)網(wǎng)絡(luò)穩(wěn)定時(shí),當(dāng)前實(shí)例新注冊(cè)的信息會(huì)被同步到其它節(jié)點(diǎn)中。
因此,Eureka 可以很好的應(yīng)對(duì)因網(wǎng)絡(luò)故障導(dǎo)致部分節(jié)點(diǎn)失去聯(lián)系的情況,而不會(huì)像 ZooKeeper 那樣使得整個(gè)注冊(cè)服務(wù)癱瘓。
③Consul
Consul 是 HashiCorp 公司推出的開源工具,用于實(shí)現(xiàn)分布式系統(tǒng)的服務(wù)發(fā)現(xiàn)與配置。
Consul 使用 Go 語言編寫,因此具有天然可移植性(支持 Linux、Windows 和 Mac OS X)。
Consul 內(nèi)置了服務(wù)注冊(cè)與發(fā)現(xiàn)框架、分布一致性協(xié)議實(shí)現(xiàn)、健康檢查、Key/Value 存儲(chǔ)、多數(shù)據(jù)中心方案,不再需要依賴其他工具(比如 ZooKeeper 等),使用起來也較為簡(jiǎn)單。
Consul 遵循 CAP 原理中的 CP 原則,保證了強(qiáng)一致性和分區(qū)容錯(cuò)性,且使用的是 Raft 算法,比 ZooKeeper 使用的 Paxos 算法更加簡(jiǎn)單。
雖然保證了強(qiáng)一致性,但是可用性就相應(yīng)下降了,例如服務(wù)注冊(cè)的時(shí)間會(huì)稍長(zhǎng)一些,因?yàn)?Consul 的 Raft 協(xié)議要求必須過半數(shù)的節(jié)點(diǎn)都寫入成功才認(rèn)為注冊(cè)成功。
在 Leader 掛掉了之后,重新選舉出 Leader 之前會(huì)導(dǎo)致 Consul 服務(wù)不可用。
默認(rèn)依賴于 SDK
Consul 本質(zhì)上屬于應(yīng)用外的注冊(cè)方式,但可以通過 SDK 簡(jiǎn)化注冊(cè)流程。而服務(wù)發(fā)現(xiàn)恰好相反,默認(rèn)依賴于 SDK,但可以通過 Consul Template(下文會(huì)提到)去除 SDK 依賴。
Consul Template
Consul 默認(rèn)服務(wù)調(diào)用者需要依賴 Consul SDK 來發(fā)現(xiàn)服務(wù),這就無法保證對(duì)應(yīng)用的零侵入性。
所幸通過 Consul Template,可以定時(shí)從 Consul 集群獲取最新的服務(wù)提供者列表并刷新 LB 配置(比如 Nginx 的 Upstream),這樣對(duì)于服務(wù)調(diào)用者而言,只需要配置一個(gè)統(tǒng)一的服務(wù)調(diào)用地址即可。
Consul 強(qiáng)一致性(C)帶來的是:
- 服務(wù)注冊(cè)相比 Eureka 會(huì)稍慢一些。因?yàn)?Consul 的 Raft 協(xié)議要求必須過半數(shù)的節(jié)點(diǎn)都寫入成功才認(rèn)為注冊(cè)成功
- Leader 掛掉時(shí),重新選舉期間整個(gè) Consul 不可用。保證了強(qiáng)一致性但犧牲了可用性。
Eureka 保證高可用(A)和最終一致性:
- 服務(wù)注冊(cè)相對(duì)要快,因?yàn)椴恍枰茸?cè)信息 Replicate 到其他節(jié)點(diǎn),也不保證注冊(cè)信息是否 Replicate 成功。
- 當(dāng)數(shù)據(jù)出現(xiàn)不一致時(shí),雖然 A,B 上的注冊(cè)信息不完全相同,但每個(gè) Eureka 節(jié)點(diǎn)依然能夠正常對(duì)外提供服務(wù),這會(huì)出現(xiàn)查詢服務(wù)信息時(shí)如果請(qǐng)求 A 查不到,但請(qǐng)求 B 就能查到。如此保證了可用性但犧牲了一致性。
其他方面,Eureka 就是個(gè) servlet 程序,跑在 servlet 容器中;Consul 則是 Go 編寫而成。
④Nacos
Nacos 是阿里開源的,Nacos 支持基于 DNS 和基于 RPC 的服務(wù)發(fā)現(xiàn)。在 Spring Cloud 中使用 Nacos,只需要先下載 Nacos 并啟動(dòng) Nacos server,Nacos 只需要簡(jiǎn)單的配置就可以完成服務(wù)的注冊(cè)發(fā)現(xiàn)。
Nacos 除了服務(wù)的注冊(cè)發(fā)現(xiàn)之外,還支持動(dòng)態(tài)配置服務(wù)。動(dòng)態(tài)配置服務(wù)可以讓您以中心化、外部化和動(dòng)態(tài)化的方式管理所有環(huán)境的應(yīng)用配置和服務(wù)配置。
動(dòng)態(tài)配置消除了配置變更時(shí)重新部署應(yīng)用和服務(wù)的需要,讓配置管理變得更加高效和敏捷。
配置中心化管理讓實(shí)現(xiàn)無狀態(tài)服務(wù)變得更簡(jiǎn)單,讓服務(wù)按需彈性擴(kuò)展變得更容易。
一句話概括就是 Nacos=Spring Cloud 注冊(cè)中心+Spring Cloud 配置中心。
作者:琦彥
編輯:陶家龍
出處:http://45dwz.com/ax2HY