服務發現如何做到持續維護服務地址在動態運維中的時效性?
遠程服務的多樣性帶來了對“服務發現”概念的雙重理解。首先,我們有“百科全書式”的服務發現,代表技術是UDDI。這種方法提供了從宏觀到微觀的信息層次,包括提供服務的企業背景(如企業實體、聯系方式、分類目錄)到具體的服務程序接口細節(例如方法名稱、參數、返回值、技術規范)。它覆蓋了服務發現過程中的廣泛信息需求。
另一端,我們看到了類似于DNS的“門牌號碼式”服務發現。這種方式專注于將服務提供者的全限定名轉換為實際的主機IP地址,其關注點更加狹窄。這種服務發現不深入到服務的具體提供商或其提供的方法細節,而是假設服務消費者已經掌握這些信息。在這里,服務的定位信息被簡化為“全限定名+端口號”的形式。
但隨著微服務的逐漸流行,服務的非正常宕機重啟和正常的上下線操作變得更加頻繁,僅靠著 DNS 服務器和負載均衡器等基礎設施,就顯得逐漸有些疲于應對,無法跟上服務變動的步伐了。
隨著分布式系統的復雜性增加,服務發現成為了一個關鍵問題,促使人們探索新的解決方案。ZooKeeper,一個分布式鍵值存儲框架,曾是解決服務注冊和發現問題的熱門工具。它在微服務的早期階段,特別是在遠程服務發現領域,占據了主導地位。然而,由于ZooKeeper是一個底層的分布式工具,它要求開發者投入大量的工作來滿足服務發現的具體需求。
2014年,經過Netflix內部長時間的實踐考驗,Eureka這一專為服務發現設計的工具宣布開源。Eureka的開源不僅標志著其成熟和可靠,而且由于其后被Spring Cloud納入,成為了Java開發者在遠程服務發現方面的首選解決方案,大大減少了服務注冊的工作量。
到了2018年,隨著Spring Cloud Eureka進入維護模式,Consul和Nacos這兩個新興的服務發現框架迅速崛起,接過了Eureka的接力棒。這些現代服務發現框架的發展已經非常成熟,它們不僅支持通過DNS或HTTP進行地址轉換,還提供了包括服務健康檢查、集中配置管理、鍵值存儲、跨數據中心數據同步等多種高級功能,標志著應用級服務發現的一個高峰。
進入云原生時代,基礎設施的靈活性被極大增強,人們開始重新關注使用基礎設施本身來實現服務發現的透明化方式。目前,探索在基礎設施和網絡協議層面,如何實現對應用幾乎無感知且便捷的服務發現,成為了研究的主要方向。
服務發現要解決注冊、維護和發現三大功能問題
服務發現流程中包含三個關鍵環節:服務注冊、服務維護、和服務發現,每個環節對于維護系統的高效運轉都至關重要。
服務注冊
服務注冊是服務發現機制的第一步。當服務啟動時,它需要以某種方式(例如,通過API調用、事件消息發布、在ZooKeeper或Etcd中記錄位置、或將信息存入數據庫等)將其坐標信息注冊到服務注冊中心。這一過程既可以由應用程序自身通過特定的注解或配置完成(如Spring Cloud的@EnableDiscoveryClient注解),也可以由容器管理框架(例如Kubernetes)自動處理。
服務維護
服務維護確保服務列表的準確性和更新性。盡管許多服務發現框架提供了服務下線的機制,但并非所有服務都能保證優雅地下線,可能因為故障或網絡問題突然中斷。因此,服務發現框架需要通過各種手段(如HTTP、TCP協議、長連接、心跳檢測、探針或進程狀態監測等)自動監控服務的健康狀況,并將不健康的服務自動下線,以避免向消費者提供無法訪問的服務地址。
服務發現
服務發現是指消費者查詢并獲得服務實際坐標信息的過程。這通常通過HTTP API請求或DNS查找操作完成,允許消費者通過服務標識(如Eureka的ServiceID、Nacos的服務名或通用的FQDN)找到服務的具體地址。盡管這里著重討論的是核心功能,許多服務發現框架還提供了一系列附加功能,如負載均衡、流量管理、鍵值存儲、元數據管理和業務分組等,進一步增強了服務發現的能力和靈活性。
為什么服務發現對 CAP 如此關注、如此敏感呢?
在概念模型中,服務中心所處的地位是這樣的:提供者在服務發現中注冊、續約和下線自己的真實坐標,消費者根據某種符號從服務發現中獲取到真實坐標,它們都可以看作是系統中平等的微服務。我們來看看這個概念模型示意圖:
服務發現在系統中的作用不同于其他服務,因為它是所有服務相互通信的基礎。就像配置中心一樣,服務發現也變得非常關鍵,因為幾乎所有服務都依賴它。如果服務發現出問題,整個系統都會受影響。因此,確保服務發現的穩定和可靠是非常重要的,需要在技術上做好準備,以防任何可能的問題。
所以,在分布式系統中,服務注冊中心一般會以內部小集群的方式進行部署,提供三個或者五個節點(通常最多七個,一般也不會更多了,否則日志復制的開銷太高)來保證高可用性。你可以看看下面給出的這個例子:
我拿前面提到的最有代表性的 Eureka 和 Consul 來舉個例子。
在分布式系統設計中,對于數據一致性和系統可用性的取舍常常是一個核心討論點,歸結為CAP理論中的兩種選擇:一致性(Consistency)與可用性(Availability),同時還要考慮分區容錯性(Partition tolerance)。Consul和Eureka這兩個服務發現工具就很好地體現了不同的設計選擇。
Consul的CP取向
Consul采用Raft協議,這是一個強調一致性的協議。在Consul的設計中,只有當多數節點確認寫入操作后,服務的注冊或變更才會被確認。這種方式確保了任何時候從集群外部讀取的服務發現信息都是一致的,即便這可能會犧牲一些可用性——在極端情況下,如果達不到多數節點的確認,服務更新操作可能會被阻塞。Consul通過這種設計,優先保證了系統的一致性(Consistency)和分區容錯性(Partition tolerance),屬于CAP理論中的CP模型。
Eureka的AP取向
與Consul不同,Eureka的設計更傾向于保證系統的可用性(Availability)。它的節點間通過異步復制來交換服務注冊信息,這意味著服務注冊或變動可以立即在當前節點上反映出來,而不需要等待這些信息被復制到其他節點。這種設計雖然提高了系統的響應速度和可用性,使得即使在部分節點不可用的情況下,服務注冊和發現仍然可以繼續工作,但它犧牲了一致性——不同節點間的信息可能會出現暫時的不一致。Eureka通過這種方式,優先保證了系統的可用性(Availability)和分區容錯性(Partition tolerance),符合CAP理論中的AP模型。
微服務架構中的一個重要設計原則是“通過服務來實現獨立自治的組件”(Componentization via Services),微服務強調通過“服務”(Service)而不是“類庫”(Library)來構建組件,這是因為兩者具有很大的差別:類庫是在編譯期靜態鏈接到程序中的,通過本地調用來提供功能;而服務是進程外組件,通過遠程調用來提供功能。