背景
服務通常需要調(diào)用其他服務。單體應用中,服務通過語言級別的方法或者過程調(diào)用另外的服務媳友。在傳統(tǒng)的分布式部署中丛版,服務運行在固定,已知的地址(主機和端口)汹来,因此可以請求的通過HTTP/REST或其他RPC機制調(diào)用续膳。然而,一個現(xiàn)代的微服務應用通常運行在虛擬或者容器環(huán)境收班,服務實例數(shù)和它們的地址都在動態(tài)改變坟岔。
因此,你需要實現(xiàn)一種機制摔桦,允許服務的客戶端向動態(tài)變更的一組短暫的服務實例發(fā)起請求社付。
問題
如何讓服務的客戶端 - API網(wǎng)關或者其他服務 - 發(fā)現(xiàn)服務實例的地址
限制
- 每個服務在特定地址(主機和端口)實例暴露一個遠程API,比如HTTP/REST邻耕,或者Thrift等等
- 服務實例的數(shù)量和他們的地址動態(tài)改變鸥咖。
- 虛擬機和容器通常分配動態(tài)IP。
- 服務實例數(shù)可能動態(tài)變化兄世。比如啼辣,EC2 Autoscaling Group基于負載確定實例數(shù)。
解決方案
當對一個服務發(fā)起請求時御滩,客戶端對運行在一個已知地址的路由(也叫做負載均衡)發(fā)起請求鸥拧。路由查詢服務注冊中心,可能構建在路由內(nèi)艾恼,將請求轉發(fā)給可用的服務實例住涉。
下圖介紹了這個模式的結構。
示例
AWS Elastic Load Balancer(ELB)是服務端服務發(fā)現(xiàn)路由的一個例子钠绍∮呱客戶端對ELB發(fā)起HTTP(s)請求(或者開放的TCP連接),這將在一組EC2實例間負載均衡這些請求柳爽。ELB不進可以負載均衡外部請求媳握,如果部署在VPC,也可以負載均衡內(nèi)部請求磷脯。ELB通常也有服務注冊中心一樣的功能蛾找。EC2實例通過API調(diào)用直接注冊,或者作為auto-scaling group的一部分自動注冊赵誓。
一些集群解決方案打毛,比如Kubernetes 和 Marathon 在每個主機都運行一個代理柿赊,擁有服務端服務發(fā)現(xiàn)路由的功能。為了訪問服務幻枉,客戶端采用分配給服務的端口來里恩杰本地代理碰声。本地代理將這部分請求轉發(fā)到集群中運行在某處的服務實例。
結果
服務端服務發(fā)現(xiàn)有幾個優(yōu)勢:
- 對比客戶端服務發(fā)現(xiàn)熬甫,由于客戶端不在處理服務發(fā)現(xiàn)胰挑,因此代碼更簡單。相反椿肩,客戶端簡單的對路由發(fā)起請求
- 一些云環(huán)境提供了這部分功能瞻颂,比如AWS Elastic Load Balancer
服務端服務發(fā)現(xiàn)也有如下弊端:
- 除非它是云環(huán)境的一部分,路由必須是另外的系統(tǒng)組件郑象,需要安裝和配置贡这。它也需要備份以滿足可用性和容量。
- 路由必須實現(xiàn)必要的通信協(xié)議(比如HTTP扣唱,gRPC藕坯,Thrift等等)团南,除非他是個基于TCP協(xié)議的路由
- 比起使用客戶端服務發(fā)現(xiàn)噪沙,需要更多的網(wǎng)絡跳數(shù)
相關模式
- 一個使用了 服務注冊中心 的路由
- 路由必須使用 斷路器模式 來調(diào)用服務
- 客戶端服務發(fā)現(xiàn) 是個替代方案