原文地址:https://microservices.io/patterns/server-side-discovery.html
服務之間需要互相呼叫,在單體架構中,服務之間的互相呼叫直接通過程式語言層面的方法呼叫就搞定了。在傳統的分散式應用的部署中,服務地址和埠是固定並且提前預知的,所以只需要簡單的 HTTP/REST 呼叫或者其他的 RPC 機制直接呼叫即可。但是在當下的雲原生微服務體系中,微服務大多在某個虛擬機器或者某個容器下執行,服務例項數量以及提供服務的地址以及埠都是不固定的,可以理解為,這些服務例項都是臨時的。所以,需要實現使服務客戶端能夠對一組動態變化的臨時服務例項發請求的機制。
提出問題
某個服務的客戶端,API閘道器或者一些其他需要發現服務例項的服務,如何知道服務例項的位置?
考慮因素
- 服務的每個例項都在特定的位置(主機和埠)暴露一個遠端 API,例如 HTTP/REST 或 Thrift 等
- 服務例項的數量及其位置都會動態變化
- 虛擬機器和容器通常分配動態 IP 地址
- 服務例項的數量可能動態變化。例如,AWS 的 EC2 自動擴容組可以根據 LOAD(負載)動態調整例項數量。
解決方案
當想請求一個服務時,客戶端通過執行在已知位置的路由器(即負載均衡器)發出請求。這個負載均衡器查詢註冊中心要呼叫的服務有哪些例項,或者登錄檔其實就整合在負載均衡器中,然後把請求轉發到對應的例項。如下圖所示:
舉例
AWS 彈性負載均衡器(ELB)是伺服器端發現路由器的一個例子。客戶端將 HTTP 請求(或者其他應用協議的 TCP 連結請求)發到 ELB,ELB 負責在一組 EC2 例項中負載均衡。ELB 可以負載均衡來自外網的請求,也可以部署在VPC中負載均衡內部的請求。ELB 也作為服務註冊中心,EC2 例項可以通過 API 呼叫顯式地向 ELB 註冊,或者作為自動擴容組的一部分自動註冊。
一些叢集解決方案,例如 Kubernetes 和 Marathon, 在每個主機上執行一個作為服務端服務發現的代理。當需要訪問一個服務的時候,客戶端訪問本地代理,這個代理會將請求轉發到叢集中相應的服務例項上。
分析
- 伺服器端服務發現有許多優點:
- 相比較客戶端發現,客戶端程式碼幾乎沒有侵入,因為它不需要處理發現。相反,客戶機只是向路由器發出請求。
- 一些雲環境提供了這種功能,例如 AWS ELB
- 它還存在以下缺點:
- 除非雲環境中有負載均衡器,否則需要部署這樣一個額外元件,並且還需要多例項部署來滿足可用性和負載能力。
- 除非負載均衡器是基於 tcp 的路由器,否則必須支援必要的應用通訊協議(例如 HTTP、grpc、thspace 等)。
- 相對於客戶端服務發現來說,需要更多的網路跳轉
相關的設計模式
- 負載均衡器使用註冊中心
- 負載均衡器可能會使用斷路器呼叫服務
- 客戶端服務發現是另一種替代解決方案