微服務(wù)架構(gòu)中的服務(wù)注冊(cè)與發(fā)現(xiàn)有哪些?Zookeeper、Eureka、Nacos、Consul 都有什么區(qū)別,實(shí)現(xiàn)原理是什么?
隨著單體應(yīng)用的拆分,我們面臨的首要問(wèn)題就是采用哪種方式實(shí)現(xiàn)服務(wù)間的調(diào)用,像之前單體應(yīng)用可能直接在配置或數(shù)據(jù)庫(kù)保存調(diào)用方的域名 IP 信息等。
但拆分后服務(wù)實(shí)例信息眾多,且隨著服務(wù)動(dòng)態(tài)擴(kuò)縮容,服務(wù)運(yùn)行時(shí)信息一直變化,那么我們就需引入注冊(cè)中心幫助我們解決這類(lèi)問(wèn)題了。
今天我們來(lái)聊一聊微服務(wù)架構(gòu)中的服務(wù)注冊(cè)與發(fā)現(xiàn)有哪些?Zookeeper、Eureka、Nacos、Consul都有什么區(qū)別,他們的實(shí)現(xiàn)原理是什么?
引入注冊(cè)中心后
在微服務(wù)架構(gòu)中,服務(wù)注冊(cè)與發(fā)現(xiàn)是一個(gè)至關(guān)重要的功能。它確保了分布式系統(tǒng)中各個(gè)微服務(wù)之間能夠動(dòng)態(tài)地相互定位和通信。常見(jiàn)的服務(wù)注冊(cè)中心有 Eureka、Zookeeper、Consul 和 Nacos
我們來(lái)看下實(shí)際項(xiàng)目中要如何選擇合適的注冊(cè)中心呢?
Eureka
Eureka 是由 Netflix 提供的服務(wù)注冊(cè)與發(fā)現(xiàn)框架,通常用于大規(guī)模的微服務(wù)系統(tǒng)。它的架構(gòu)分為兩部分:Eureka Server 和 Eureka Client,這是 Eureka 的架構(gòu)圖。
- Eureka Server:負(fù)責(zé)提供注冊(cè)中心的服務(wù),所有微服務(wù)實(shí)例都注冊(cè)到 Eureka Server 中,其他微服務(wù)通過(guò) Eureka Client 來(lái)發(fā)現(xiàn)服務(wù)。
- Eureka Client:微服務(wù)實(shí)例作為客戶端,定期向 Eureka Server 注冊(cè)自己并更新健康狀態(tài)。這里包含了 Application Service(服務(wù)提供者)和 Application Client(服務(wù)消費(fèi)者)。
“那么,Eureka 是如何保證 AP 的呢?
- 集群:由上圖可看出 Eureka Server 多個(gè)實(shí)例之間都是對(duì)等的,每個(gè)都是其它節(jié)點(diǎn)的副本,是一種去中心化的架構(gòu)。
- 心跳:Client 通過(guò)發(fā)送心跳到 Server 以維持和更新注冊(cè)表中服務(wù)實(shí)例元數(shù)據(jù)的有效性。當(dāng)在一定時(shí)長(zhǎng)內(nèi)(默認(rèn) 90s),Server 沒(méi)有收到 Client 的心跳信息,會(huì)把服務(wù)實(shí)例的信息從注冊(cè)表中刪除。
- 自我保護(hù)機(jī)制:當(dāng) Eureka Server 節(jié)點(diǎn)在短時(shí)間內(nèi)丟失過(guò)多的心跳時(shí)(15 分鐘超過(guò) 85%節(jié)點(diǎn)沒(méi)有正常返回心跳),那么這個(gè)節(jié)點(diǎn)就會(huì)進(jìn)入自我保護(hù)模式。
“什么是 Eureka 的自我保護(hù)機(jī)制?
- Eureka 不再剔除沒(méi)有正常返回心跳的服務(wù)。
- Eureka 仍可以接受新服務(wù)注冊(cè)請(qǐng)求,但是不會(huì)同步到其它 Server 節(jié)點(diǎn)。
- 當(dāng)網(wǎng)絡(luò)恢復(fù)穩(wěn)定時(shí),之前新注冊(cè)的信息會(huì)再次同步到其它節(jié)點(diǎn)上。
所以 Eureka 遵循的是 AP(Availability + Partition tolerance)。它犧牲了數(shù)據(jù)一致性,尤其是在網(wǎng)絡(luò)分區(qū)發(fā)生時(shí)。Eureka 實(shí)現(xiàn)了 "最終一致性" 的策略,允許系統(tǒng)在出現(xiàn)故障時(shí)繼續(xù)提供可用的服務(wù)。
Zookeeper
“Zookeeper 是如何實(shí)現(xiàn)注冊(cè)中心的呢?
Zookeeper 的數(shù)據(jù)模型基于一種叫做 ZNode(Zookeeper 節(jié)點(diǎn))的概念,在 Zookeeper 中,服務(wù)注冊(cè)和發(fā)現(xiàn)的核心思想是利用臨時(shí)節(jié)點(diǎn)來(lái)存儲(chǔ)服務(wù)實(shí)例的信息。具體過(guò)程如下:
- 創(chuàng)建臨時(shí)節(jié)點(diǎn):當(dāng)一個(gè)服務(wù)啟動(dòng)時(shí),它會(huì)向 Zookeeper 注冊(cè)自己。通常,服務(wù)會(huì)在某個(gè)目錄(如 /services)下創(chuàng)建一個(gè)臨時(shí)節(jié)點(diǎn)。每個(gè)服務(wù)實(shí)例會(huì)被注冊(cè)為一個(gè)獨(dú)特的臨時(shí)節(jié)點(diǎn)。
存儲(chǔ)路徑示例:
/services/payment-service/instance-1
/services/payment-service/instance-2
//payment-service:支付服務(wù)名稱(chēng)
//instance-1:實(shí)例唯一標(biāo)識(shí)符,Ip端口信息。
- watch 機(jī)制:Zookeeper 支持客戶端對(duì)節(jié)點(diǎn)的監(jiān)視機(jī)制(Watch)。當(dāng)服務(wù)上線時(shí),Zookeeper 會(huì)通知客戶端,客戶端會(huì)更新可用服務(wù)列表。當(dāng)某個(gè)服務(wù)實(shí)例斷開(kāi)與 Zookeeper 的連接時(shí),Zookeeper 會(huì)刪除該臨時(shí)節(jié)點(diǎn),并通知客戶端,客戶端可以去掉失效的服務(wù)實(shí)例。
ZooKeeper 是基于 CP 來(lái)設(shè)計(jì)的,即任何時(shí)刻對(duì) ZooKeeper 的訪問(wèn)請(qǐng)求能得到一致的數(shù)據(jù)結(jié)果,同時(shí)系統(tǒng)對(duì)網(wǎng)絡(luò)分割具備容錯(cuò)性,但是它不能保證每次服務(wù)請(qǐng)求的可用性。
從實(shí)際情況來(lái)分析,在使用 ZooKeeper 獲取服務(wù)列表時(shí),如果 zookeeper 正在選主,或者 ZooKeeper 集群中半數(shù)以上機(jī)器不可用,那么將無(wú)法獲得數(shù)據(jù)。所以說(shuō),ZooKeeper 不能保證服務(wù)可用性。
Nacos
Nacos 的關(guān)鍵特性:
- 服務(wù)發(fā)現(xiàn)和服務(wù)健康監(jiān)測(cè):Nacos 支持基于 DNS 和基于 RPC 的服務(wù)發(fā)現(xiàn)。提供對(duì)服務(wù)的實(shí)時(shí)的健康檢查,支持傳輸層(PING 或 TCP)和應(yīng)用層 (如 HTTP、MySQL、用戶自定義)的健康檢查。
- 動(dòng)態(tài)配置服務(wù):Nacos 支持的動(dòng)態(tài)配置,提供了配置版本跟蹤、金絲雀發(fā)布、一鍵回滾配置以及客戶端配置更新?tīng)顟B(tài)跟蹤在內(nèi)的一系列開(kāi)箱即用的配置管理特性。
- 動(dòng)態(tài) DNS 服務(wù):Nacos 提供了動(dòng)態(tài) DNS 服務(wù),支持權(quán)重路由,使得中間層負(fù)載均衡、更靈活的路由策略、流量控制以及數(shù)據(jù)中心內(nèi)網(wǎng)的簡(jiǎn)單 DNS 解析服務(wù)。
- 服務(wù)及其元數(shù)據(jù)管理:Nacos 可以幫助微服務(wù)平臺(tái)建設(shè)的視角管理數(shù)據(jù)中心的所有服務(wù)及元數(shù)據(jù)。
Nacos 生態(tài)圖
如 Nacos 全景圖所示,Nacos 無(wú)縫支持一些主流的開(kāi)源生態(tài)。
Nacos 作為注冊(cè)中心架構(gòu)圖:
Nacos 作為注冊(cè)中心,它是支持戶根據(jù)需求選擇 一致性優(yōu)先(CP) 或 可用性優(yōu)先(AP) 模式的。
- CP 模式:Nacos 集群通過(guò)使用 Raft 協(xié)議確保一致性,通過(guò) Raft 協(xié)議確保集群內(nèi)的大部分節(jié)點(diǎn)在某一時(shí)刻保持一致的數(shù)據(jù)副保持本。如果發(fā)生網(wǎng)絡(luò)分區(qū)時(shí),為了保證數(shù)據(jù)一致性,Nacos 可能會(huì)將某些請(qǐng)求拒絕。
- AP 模式:Nacos 集群可以容忍部分節(jié)點(diǎn)的失效或者網(wǎng)絡(luò)分區(qū),并繼續(xù)提供服務(wù)。AP 模式下,Client 會(huì)從不同節(jié)點(diǎn)獲取到不同的數(shù)據(jù)副本,這種模式主要為了提供系統(tǒng)的可用性。
可以通過(guò)更改 Nacos 的配置文件 conf/application.properties 切換 AP 或 CP 模式:
nacos.core.protocol.distro.data.sync.mode
Raft表示CP模式,Async表示AP模式
默認(rèn)情況下,Nacos 會(huì)采用 AP 模式,因?yàn)榇蠖嗲闆r下作為注冊(cè)中心,微服務(wù)架構(gòu)更看重它對(duì)服務(wù)注冊(cè)發(fā)現(xiàn)高可用的要求。
Consul
Consul 是 HashiCorp 公司推出的開(kāi)源工具,Consul 由 Go 語(yǔ)言開(kāi)發(fā),部署起來(lái)非常容易,只需要極少的可執(zhí)行程序和配置文件,具有綠色、輕量級(jí)的特點(diǎn)。
Consul 的特點(diǎn):
- 服務(wù)發(fā)現(xiàn):Consul 提供了 HTTP 或 DNS 的方式來(lái)注冊(cè)、發(fā)現(xiàn)服務(wù)。
- 健康檢查:Consul Client 可以提供任意數(shù)量的健康檢查,可以根據(jù)返回結(jié)果比如“200”或者與本地負(fù)載(“內(nèi)存占用是否低于 90%”),來(lái)判斷服務(wù)是否處于健康狀態(tài)。
- key/Value 存儲(chǔ):Consul 數(shù)據(jù)采用 key/value 結(jié)構(gòu)存儲(chǔ),非常靈活方便。
- 安全服務(wù)通信:Consul 可以為服務(wù)生成和分發(fā) TLS 證書(shū),以建立相互的 TLS 連接。
- 多數(shù)據(jù)中心:Consul 天然支持多數(shù)據(jù)中心。
**Consul 架構(gòu)圖 **
由上圖可看出,Consul 分為 Client 和 Server 兩種節(jié)點(diǎn)(所有的節(jié)點(diǎn)也被稱(chēng)為 Agent):
- Server 節(jié)點(diǎn)保存數(shù)據(jù),Server 節(jié)點(diǎn)有一個(gè) Leader 和多個(gè) Follower,Leader 節(jié)點(diǎn)會(huì)將數(shù)據(jù)同步到 Follower,Server 的數(shù)量推薦是 3 個(gè)或者 5 個(gè),在 Leader 掛掉的時(shí)候會(huì)啟動(dòng)選舉機(jī)制產(chǎn)生一個(gè)新的 Leader。
- Client 負(fù)責(zé)健康檢查及轉(zhuǎn)發(fā)數(shù)據(jù)請(qǐng)求到 Server。
Consul 采用的 Raft 協(xié)議來(lái)保證集群內(nèi)多個(gè)節(jié)點(diǎn)的數(shù)據(jù)一致性,所以是采用的 CP 模式。
最后
最后,我們來(lái)看下各注冊(cè)中心的對(duì)比:
Eureka | Zookeeper | Nacos | Consul | |
一致性協(xié)議 | AP | CP | CP、AP | CP |
健康檢查 | 心跳 | Keep Alive | TCP/HTTP/MYSQL | TCP/HTTP/gRPC/Cmd |
負(fù)載均衡策略 | Ribbon | -- | 權(quán)重/metadata/Selector | Fabio |
訪問(wèn)協(xié)議 | HTTP | TCP | HTTP/DNS | HTTP/DNS |
多數(shù)據(jù)中心 | 支持 | 不支持 | 支持 | 支持 |
跨注冊(cè)中心同步 | 支持 | 不支持 | 支持 | 支持 |
SpringCloud 集成 | 支持 | 支持 | 支持 | 支持 |
K8S 集成 | 支持 | 支持 | 支持 | 支持 |