模式: 客戶端服務發現
背景
不同服務之間通常需要相互調用。在單體應用程序當中,服務間通過語言層級的方法或者過程實現相互調用。在傳統的分布式系統部署下,服務在固定並且已知的位置(主機與端口)運行,從而確保各服務可利用HTTP/REST或者某種RPC機制進行相互調用。然而,現代化微服務應用程序中通常在虛擬化或者容器化環境中運行,在這樣的環境中服務的實例數量和位置是動態變化的。
因此,要想實現客戶端向動態變化的一組服務端實例發送請求,我們必須采用新的機制。
問題
服務的客戶端——包括API網關或者其它服務——如何才能獲取服務端實例的位置?
需求
- 每一服務實例都會在特定位置(主機與端口)通過HTTP/REST或者Thrift等方式發布一個遠程API。
- 服務端實例的具體數量及位置會發生動態變化。
- 虛擬機與容器通常會被分配動態IP地址。
- 服務實例的數量會發生動態變化。例如,EC自動伸縮組會根據負載情況隨時調整實例數量。
方案
在向某一服務發送請求時,客戶端會通過查詢 Service Registry,即服務注冊表,以獲取該服務實例的位置。該注冊表中包含全部服務的位置。
以下示意圖展現了這種模式的結構:
而這正是微服務基底框架的典型處理方式。
例子
Netflix OSS 正是客戶端發現機制的典型代表:
- Eureka 充當其中的服務注冊表
- Ribbon Client 是一套HTTP客戶端,負責向 Eureka 發出查詢任務並將 HTTP 請求路由至可用的服務實例。
結果
客戶端發現機制擁有以下優勢:
- 相較於服務器端服務發現,其活動部件與網絡中轉數量更少。
客戶端發現機制亦存在着以下弊端:
- 這一模式使客戶端與服務注冊表相耦合。
- 需要為應用程序中使用的每種編程語言/框架建立客戶端服務發現邏輯,例如Java/Scala以及JavaScript/Node JS。舉例來說,Netflix Prana 就為非 JVM 客戶端提供了一套基於HTTP代理的服務發現方案。
相關模式
- 服務注冊表 - 服務發現的基礎
- 微服務的基底 - 客戶端服務發現是微服務基底模塊的職責之一
- 服務器端服務發現 是另一種可選的方案





