微服務4:服務註冊與發現

翁智華發表於2022-01-20

★ 微服務系列

微服務1:微服務及其演進史

微服務2:微服務全景架構 

微服務3:微服務拆分策略

微服務4:服務註冊與發現

1 微服務的註冊與發現

我們前面在全景架構中對服務註冊與發現做了大致的說明,本章我們著重詳細說明微服務下注冊與發現的這個能力。

微服務註冊與發現類似於生活中的"電話通訊錄"的概念,它記錄了通訊錄服務和電話的對映關係。在分散式架構中,服務會註冊進去,當服務需要呼叫其它服務時,就這裡找到服務的地址,進行呼叫。

步驟如下:

1、你先要把"好友某某"記錄在通訊錄中。

2、撥打電話的時候通過通訊錄中找到"好友某某",並撥通回電話。

3、當好友某某電話號碼更新的時候,需要通知到你,並修改通訊錄服務中的號碼。

從這個過程中我們看到了一些特點:

1、把 "好友某某" 的電話號碼寫入通訊錄中,統一在通訊錄中維護,後續號碼變更也是更新到通訊錄中,這個過程就是服務註冊的過程。

2、後續我們通過"好友某某"就可以定位到通訊錄中的電話號碼,並撥通電話,這個過程理解為服務發現的過程。

而我們微服務架構中的服務註冊與發現結構如下圖所示

 

圖片中是一個典型的微服務架構,這個結構中主要涉及到三大角色:

provider - 服務提供者

consumer - 服務消費者

register center - 註冊中心

它們之間的關係大致如下:

1、每個微服務在啟動時,將自己的網路地址等資訊(微服務的ServiceName、IP、Port、MetaData等)註冊到註冊中心,註冊中心儲存這些資料。

2、服務消費者從註冊中心查詢服務提供者的地址,並通過該地址呼叫服務提供者的介面。

3、各個微服務與註冊中心使用一定機制(例如心跳)通訊。如果註冊中心與某微服務長時間無法通訊,就會登出該例項。

優點如下:

1、解耦:服務消費者跟服務提供者解耦,各自變化,不互相影響

2、擴充套件:服務消費者和服務提供者增加和刪除新的服務,對於雙方沒有任何影響

3、中介者設計模式:用一箇中介物件來封裝一系列的物件互動,這是一種多對多關係的中介者模式。

從功能上拆開主要有三塊:服務註冊、服務發現,和註冊中心。我們一個一個來看。

1.1 服務註冊

如圖中,為Register註冊中心註冊一個服務資訊,會將服務的資訊:ServiceName、IP、Port以及服務例項MetaData後設資料資訊寫入到註冊中心。當服務發生變化的時候,也可以更新到註冊中心。

 

服務提供者(服務例項) 的服務註冊模型是一種簡單、容易理解、流行的服務註冊模型,其在多種技術生態中都有所體現:

1、在K8S生態中,通過 K8S Service服務資訊,和Pod的 endpoint(用來記錄service對應的pod的訪問地址)來進行註冊。

2、在Spring Cloud生態中,應用名 對應 服務Service,例項 IP + Port 對應 Instance例項。比較典型的就是A服務,後面對應有多個例項做負載均衡。 

3、在其他的註冊元件中,比如 Eureka、Consul,服務模型也都是 服務→ 服務例項。

可以認為服務例項是一個真正的實體的載體,服務是對這些相同能力或者相同功能服務例項的一個抽象。

 

1.2 服務發現

服務發現實際就是我們查詢已經註冊好的服務提供者,比如 p->p.queryService(serviceName),通過服務名稱查詢某個服務是否存在,如果存在,

返回它的所有例項資訊,即一組包含ip 、 port 、metadata後設資料資訊的endpoints資訊。

這一組endpoints資訊一般會被快取在本地,如果註冊中心掛掉,可保證段時間內依舊可用,這是去中心化的做法。對於單個 Service 後面有多個 Instance的情況(如上圖),做 load balance。

服務發現的方式一般有兩種:

1、拉取的方式:服務消費方(Consumer)主動向註冊中心發起服務查詢的請求。

2、推送的方式:服務訂閱/通知變更(下發):服務消費方(Consumer)主動向註冊中心訂閱某個服務,當註冊中心中該服務資訊發生變更時,註冊中心主動通知消費者。 

1.3 註冊中心

註冊中心提供的基本能力包括:提供服務註冊、服務發現 以及 健康檢查。

服務註冊跟服務發現上面已經詳細介紹了, 健康檢查指的是指註冊中心能夠感知到微服務例項的健康狀況,便於上游微服務例項及時發現下游微服務例項的健康狀況。採取必備的訪問措施,如避免訪問不健康的例項。

主要的檢查方式包括:

1、服務Provider 進行 TTL 健康彙報(Time To Live,微服務Provider定期向註冊中心彙報健康狀態)。

2、註冊中心主動檢查服務Provider介面。

綜合我們前面的內容,可以總結下注冊中心有如下幾種能力:

1、高可用

這個主要體現在兩個方面。一個方面是,註冊中心本身作為基礎設施層,具備高可用;第二種是就是前面我們說到的去中心化,極端情況下的故障,短時間內是不影響微服務應用的呼叫的

2、視覺化操作

常用的註冊中心,類似 Eureka、Consul 都有比較豐富的管理介面,對配置、服務註冊、服務發現進行視覺化管理。

3、高效運維

註冊中心的文件豐富,對運維的支援比較好,並且對於服務的註冊是動態感知獲取的,方便動態擴容。

4、許可權控制

資料是具有敏感性,無論是服務資訊註冊或服務是呼叫,需要具備許可權控制能力,避免侵入或越權請求

5、服務註冊推、拉能力

這個前面說過了,微服務應用程式(服務的Consumer),能夠快速感知到服務例項的變化情況,使用拉取或者註冊中心下發的方式進行處理。 

 

2 現下的主流注冊中心

2.1 Eureka

2.1.1 介紹

Eureka是Netflix OSS套件中關於服務註冊和發現的解決方案。因為Spring Cloud 在它的微服務解決方案中對Eureka進行了整合,並作為優先推薦方案進行宣傳,所以早期有用 Spring Cloud 來建設微服務系統的同學會比較熟悉。

目前大量公司的微服務系統中依舊使用Eureka作為註冊中心,它的核心設計思想也被後續大量註冊中心產品借鑑。但目前 Eureka 2.0已經停止維護,所以新的微服務架構設計中,不再建議使用。

Spring Cloud Netflix主要分為兩個部分:

1、Eureka Server: 作為註冊中心Server端,向微服務應用程式提供服務註冊、發現、健康檢查等能力。

2、Eureka Client:  微服務應用程式Client端,用以和Eureka Server進行通訊。

 

 Eureka有比較友好的管理介面,如上圖所示:

1、System Status:顯示當前Eureka Server資訊。

2、Instances Current registered with Eureka:在Eureka Server當前註冊的資料,在Spring Cloud生態中,被註冊的服務可以唄發現並羅列在這個地方。

3、General Info:基本資訊,如cpu、記憶體、環境等。

2.1.2 整體架構

 

Eureka Server可以執行多個例項來構建叢集,解決單點問題,但不同於ZooKeeper的選舉leader的過程,Eureka Server採用的是Peer to Peer對等通訊。

所以他有如下特點:

1、去中心化的架構:無master/slave區分,每一個Peer都是對等的。在這種架構中,節點通過彼此互相註冊來提高可用性,每個節點需要新增一個或多個有效的serviceUrl指向其他節點。每個節點都可被視為其他節點的副本。

2、故障轉移/故障恢復:如果某臺Eureka Server當機,Eureka Client的請求會自動切換到新的Eureka Server節點,當當機的伺服器重新恢復後,Eureka會再次將其納入到伺服器叢集管理之中。

3、節點複製:當節點開始接受客戶端請求時,所有的操作都會進行replicateToPeer(節點間複製)操作,將請求複製到其他Eureka Server當前所知的所有節點中。

同理,一個新的Eureka Server節點啟動後,會首先嚐試從鄰近節點獲取所有例項登錄檔資訊,完成初始化。

4、CAP模式:複製演算法非強一致性演算法,而是當有資料寫入時,Eureka Server將資料同步給其他的節點,因此Eureka在CAP提系統(一致性、可用性、分割槽容錯性)是典型的AP系統。

2.1.3 接入Spring Cloud

 

如上圖所示:

1、Provider 服務提供者:服務向註冊中心註冊服務資訊,即 服務 -> 服務例項 資料模型, 同時定時向註冊中心彙報健康檢查,如果一定時間內(一般90s)沒有進行心跳彙報,則會被註冊中心剔除。

所以這邊注意,註冊中心感知到應用下線並進行剔除這個過程可能比較長。 

2、Consumer 服務消費者:服務向註冊中心獲取所需服務對應的服務例項資訊。這邊需要注意,Eureka不支援訂閱,因此在Spring Cloud生態中,通過定時拉取方式從註冊中心中獲取所需的服務例項資訊。

3、Remote Call 遠端呼叫:Consumer從註冊中心獲取的Provider的例項資訊,通過 Load Balance的策略,確定一個實際的例項,發起遠端呼叫。 

2.2 ZooKeeper

2.2.1 介紹

作為一個分散式的、開源的協調服務,ZooKeeper實現了一系列基礎功能,包括簡單易用的介面。

這些介面被用來實現服務的註冊與發現功能。並實現一些高階功能,如資料同步、分散式鎖、配置中心、叢集選舉、命名服務等。

  

在資料模型上,類似於傳統的檔案系統,節點型別分為:

1、持久節點:節點建立後,就一直存在,除非執行刪除操作,主動刪掉這個節點。

2、臨時節點(註冊中心場景下的主要實現機制):臨時節點的生命週期和客戶端會話繫結。也就是說,如果客戶端會話失效,那麼這個節點就會自動被清除掉。

在實際場景下,微服務啟動的時候,會建立一個服務臨時節點,等把服務停止,短時間後節點就沒有了。

 

Zookeeper有如下特點:

1、最終一致性:為客戶端展示同一檢視,這是zookeeper最重要的功能。
2、可靠性:如果訊息被到一臺伺服器接受,那麼它將被所有的伺服器接受。
3、實時性:Zookeeper不能保證兩個客戶端能同時得到剛更新的資料,如果需要最新資料,應該在讀資料之前呼叫sync()介面。
4、等待無關(wait-free):慢的或者失效的client不干預快速的client的請求。
5、原子性:更新只能成功或者失敗,沒有中間狀態。
6、順序性:所有Server,同一訊息釋出順序一致。

2.2.2 整體架構

 

上圖是Zookeeper 的服務架構,他有如下流程:

1、 多個節點組成分散式架構,每個Server在記憶體中儲存一份資料; 

2、通過選舉產生leader,通過 Paxos(帕克索斯)強一致性演算法 進行保證,是典型的CP結構。

3、Leader負責處理資料更新等操作(Zab協議);

2.2.3 接入Dubbo生態

 

上圖中的角色如下:

Provider:提供者,服務釋出方

Consumer:消費者, 呼叫服務方

Container:Dubbo容器.依賴於Spring容器

Registry:註冊中心,當Container啟動時把所有可以提供的服務列表上Registry中進行註冊,告訴Consumer提供了什麼服務,以及服務方的位置

Monitor:監聽器

說明:ZooKeeper在註冊中心方面對Dubbo生態支援的比較好。服務提供者Providerzai Container啟動時主動向註冊中心Registry ZooKeeper中註冊資訊。

服務消費者Consumer啟動時向註冊中心Registry ZooKeeper中訂閱註冊中心,當Provider的資訊發生變化時,註冊中心ZooKeeper會主動向Consumer進行推送通知變更。

這邊注意與Eureka的區別,這是主動推送通知,是註冊中心下發的操作。

2.3 Consul

2.3.1 介紹

Consul是HashiCorp推出的一款軟體,是一個Service Mesh解決方案,提供了功能豐富的控制面功能:

1、Service Discovery(服務發現)

2、Configuration(配置化)

3、Segmentation Functionality

這些功能可以根據需要獨立使用,或者將它們一起使用用來構建完整的Service Mesh。

Consul提供的關鍵功能如下:

1、Service Discovery:服務註冊/發現功能。

2、Health Checking:健康檢查,豐富的健康檢查方式;

3、KV Store:KV儲存功能,可應用多種場景,如動態配置儲存,分散式協調、leader選舉等。

4、Multi DataCenter:多資料中心。

2.3.2 整體架構

  

如上圖為Consul的架構,這邊對技術點做一下說明:

1、Raft: 一種分散式一致性演算法,Consul使用該演算法報紙強一致性,所以也是典型的CP模式

2、Client:Client是一種agent,其將會重定向所有的RPC 請求到Server。Client是無狀態的,其主要參與LAN Gossip協議池。其佔用很少的資源,並且消耗很少的網路頻寬。

3、Server:Server是一種agent,其包含了一系列的責任包括:參與Raft協議寫半數(Raft Quorum)、維護叢集狀態、響應RPC響應、和其他Datacenter通過WAN gossip交換資訊和重定向查詢請求至leader或者遠端Datacenter。

4、Datacenter: Datacenter其是私有的、低延遲、高頻寬的網路環境,去除了在公共網路上的網路互動。

5、Consensus: Consensus一致性在leader 選舉、順序執行transaction 上。當這些事務已經提交至有限狀態機(finite-state machine)中,Consul定義consensus作為複製狀態機的一致性。本質上使用實現了Raft協議,對於具體實現細節可參考 Consensus Protocol。

6、Gossip:Consul使用了Serf,其提供了Gossip協議多種用途,Serf提供成員關係、失敗檢查和事件廣播。

7、LAN Gossip: Local Area Network Gossip其包含在同一個網路環境或Datacenter的節點。

8、WAN Gossip: Wide Area Network Gossip 其只包含Server節點,這些server分佈在不同的datacenter中,其主要通過因特網或廣域網相互交流。

9、RPC: 遠端過程呼叫,用於服務之間的通訊。

10、CAP抉擇:在高可用方面,Consul使用Raft協議作為其分散式一致性協議,本身對故障節點有一定的容忍性,在單個DataCenter中Consul叢集中節點的數量控制在2*n + 1個節點,其中n為可容忍的當機個數,通常為3個節點。

所以是典型的CP模式。

 

根據Consul 的選舉機制和服務原理,我們有兩個注意點 :

1、部署Consul Service 節點應該奇數為宜,因為+1的偶數節點和奇數節點可容忍的故障數是一樣的,比如上圖3和4,另一方面,偶數個節點在選主節點的時候可能會出現二分選票的情況,還得重新選舉。

2、Consul Service 節點數不是越多越好,雖然Server數量越多可容忍的故障數越多,但是Raft進行日誌複製也是很耗時間的,而且Server數量越多,效能越低,所以結合實際場景,一般建議Server部署3個即可。 

有興趣的同學可以去Consul官網看看它的選舉機制,還可以對比下Redis中Sentinel模式。

2.3.3 生態對接

對接Spring Cloud生態

Consul作為註冊中心,整合在Spring Cloud生態。可以看出,跟Eureka對接到Spring Cloud 生態的過程很像。

但是這邊的健康檢查更豐富,可以有多種不同的的Check方式:

  • Script check(Script+ Interval)
  • 基於HTTP請求
  • 基於tcp請求
  • 基於grpc請求

2.4 總結對比

4種註冊中心技術對比
指標 Eureka Zookeeper Consul Etcd
一致性協議 AP CP(Paxos演算法) CP(Raft演算法) CP(Raft演算法)
健康檢查 TTL(Time To Live) TCP Keep Alive TTL\HTTP\TCP\Script Lease TTL KeepAlive
watch/long polling 不支援 watch long polling watch
雪崩保護 支援 不支援 不支援 不支援
安全與許可權 不支援 ACL ACL RBAC
是否支援多資料中心
是否有管理介面 否(可用第三方ZkTools)
Spring Cloud 整合 支援 支援 支援 支援
Dubbo 整合 不支援 支援 支援 不支援
K8S 整合 不支援 不支援 支援 支援

  

這邊是對業內4種註冊中心各緯度上的對比,Eureka是典型的AP型別,Zookeeper和Consul是典型的CP型別。如何選擇取決你的業務是傾向A:高可用性 還是 C:強一致性。

當然,業務是複雜的,在真正的技術選型時,還是要根據自己的實際業務現狀來判斷。有一些傾向,比如你的系統是Spring Cloud體系下,那優先選擇Eureka、Consul。

如果業務會更多向雲原生對齊,則Consul、Etcd會是比較優先的選擇。

相關文章