一文搞懂注冊中心的設計與實現
服務治理在微服務架構中扮演著至關重要的角色,它使得各個微服務能夠自動完成注冊和發現。本文將深入探討實現服務治理的基本方法。
首先,設想我們正在構建一個分布式服務系統。在這種系統中,服務的數量可能非常龐大,并且服務之間需要相互溝通,形成錯綜復雜的調用路徑。
面對眾多服務,我們通常會遇到兩個主要問題:
- 如何有效追蹤服務實例的數量?
- 如何監控服務實例的當前狀態?
當系統中服務數量激增,例如達到數十甚至數百個時,我們很難清楚地了解哪些服務正在運行。而且,由于自動擴展、服務重啟等操作,服務實例的運行狀態也會頻繁變動。如下圖所示:
圖片
為了更清晰地描述服務的運行狀態,我們可以對每個服務實例進行抽象化處理,并采用統一且直觀的方式來表達這些信息。如下所示:
圖片
但是,隨著服務數量的增加和服務實例狀態的不斷變化,我們如何有效管理這些實例呢?這正是服務治理所要解決的問題。通常,為了實現高效的服務治理,我們會引入注冊中心來管理服務實例。
什么是注冊中心
注冊中心是一個存儲服務實例信息的倉庫,同時也是服務提供者和消費者進行交流的樞紐。它主要提供兩項核心功能:服務注冊和服務發現。
圖片
我們看這張服務注冊流程圖就知道,對于注冊中心而言,服務的提供者和消費者都相當于是它的客戶端,所以都內嵌了專門與注冊中心實現交互的客戶端組件。
服務提供者在啟動時,會通過注冊中心的客戶端組件自動注冊自己,這個過程也被稱作服務發布。對于服務消費者而言,他們執行的是訂閱操作,而非注冊操作。通過訂閱,消費者能夠自動從注冊中心獲取已注冊服務提供者的信息,這個過程就是服務發現。
我們還可以看到,服務消費者和提供者之間存在一個明顯的區別:消費者擁有一個本地緩存,存儲了他們獲取到的服務提供者實例信息。
這個本地緩存有兩個主要作用:一是提高服務發現效率,消費者可以通過查詢本地緩存快速獲取目標服務實例信息;二是在注冊中心不可用或網絡異常時,消費者依然可以基于本地緩存調用已注冊的服務。
注冊信息變更通知機制
講到這里,我們實際上就已經了解了 。通過獲取注冊中心中的服務實例信息,我們就可以掌握系統中服務的數量以及當前的運行時狀態了。
但問題來了,一旦服務的運行狀態發生變化,我們如何及時獲取這些變更信息呢?這就需要在注冊中心引入變更通知機制:
圖片
變更通知機制是實現注冊中心的一大難點,因為這個過程涉及服務提供者、消費者和注冊中心三者之間的數據同步問題,想要在分布式環境下實現數據同步是有挑戰的。接下來,我將介紹兩種主流的實現方法:監聽機制和輪詢機制。
監聽機制
從架構設計角度來看,狀態變更管理可以利用注冊中心的發布-訂閱模式。因此也就誕生了服務監聽機制。它確保服務消費者能夠實時監控服務的更新狀態,是一種被動接收變更通知的方案,通常采用監聽器和回調機制。
圖片
服務消費者可以為具體的服務實例節點添加監聽器。當這些節點發生變化時,例如服務 B 的第一個實例不可用、服務 C 的第一個實例地址變更,或服務 D 新增了一個實例 3,注冊中心就會觸發監聽器中的回調函數,確保更新通知到每一個服務消費者。
輪詢機制
另一種確保狀態信息同步的方式是輪詢機制,這是一種主動拉取策略。服務消費者會定期調用注冊中心的服務獲取接口,以獲取最新的服務列表,并更新本地緩存。
圖片
輪詢機制實際上是一個定時器,我們需要考慮的主要問題是輪詢頻率。為了確保數據同步的及時性,輪詢頻率不能太短;但同時,考慮到輪詢對注冊中心性能的影響,也不能過于頻繁。通常,將輪詢頻率控制在幾十秒到幾分鐘之間是一個較好的選擇。
注冊中心實現工具
通過前面的分析,相信你對注冊中心的實現原理有了全面的了解。注冊中心本質上是一種架構模型。在開發過程中,為了避免重復勞動,我們通常不需要自己實現這一模型,而是可以采用業界的一些主流注冊中心實現工具,如 Consul、Zookeeper、Eureka 和 Nacos。
Consul 由 HashiCorp 公司提供,主要用于分布式環境下的服務發現與配置;Zookeeper 是 Apache 的一個頂級項目,作為分布式協調領域的代表性框架,被廣泛用于注冊中心、配置中心和分布式鎖等場景;Netflix 的 Eureka 采用了一種不同的實現方案,并集成到了微服務開發框架 Spring Cloud 中;Nacos 由阿里巴巴開發,是面向云原生應用的動態服務發現、配置和服務管理平臺。
這些工具各有特點,都實現了注冊中心的高可用性、服務實例存儲和同步功能,并提供了方便集成的客戶端組件。我們知道,注冊中心主要應用于微服務系統,主流的微服務開發框架是 Dubbo 和 Spring Cloud,它們分別使用 Zookeeper 和 Eureka 作為默認的注冊中心實現方案。
因此,接下來我們就重點探討下這兩款注冊中心工具。
Zookeeper 是“服務監聽機制”實現策略的典型代表,它本質上是一個樹形結構,可以在樹上創建臨時節點,并對節點添加監聽器。
臨時節點的客戶端與該節點建立長連接,并實時關注節點狀態。客戶端有一個回調函數,當節點狀態變化時,通過監聽器將變化傳遞到客戶端并觸發回調函數。如下圖所示:
圖片
而對于 Netflix Eureka 而言,它采用的就是典型的“輪詢機制”來實現服務實例狀態的同步,如下所示:
圖片
在 Eureka 中,客戶端和服務器端通過發送心跳來實現輪詢機制。Eureka 有一個租約概念,服務提供者需要通過續約機制來確保注冊中心中的服務實例狀態得到更新。心跳的作用是完成續約操作。
一般來說,心跳頻率是 30 秒,如果服務連續 90 秒沒有發送心跳,Eureka 服務器會認為該服務失效,并更新其狀態信息。這樣,可以確保 Eureka 服務器中服務實例信息的正確性。
服務消費者也是通過輪詢機制來獲取服務提供者的實例信息,其默認輪詢頻率同樣是 30 秒。
總結
你只需要記住,注冊中心是一種服務治理工具,它可以管理所有服務實例的運行狀態,并將這些狀態的變化同步到各個服務中。在開發分布式系統時,通過引入注冊中心,可以輕松實現對大規模服務的高效治理。


































