第四篇:服務發現機制
本文出自Service Discovery in a Microservices Architecture,作者 Chris Richardson, 寫於2015年5月19日
這是本系列文章的第四篇。
本文我們繼續探索與服務發現緊密聯絡的有關問題。
一、為什麼使用服務發現?
想象一下編寫程式碼呼叫REST
或者Thrift API
的服務,為了實現這個呼叫,你的程式碼需要知道服務例項的網路位置(IP
地址和埠)。在執行在物理硬體的傳統應用中,服務例項的網路位置是相對靜止的。例如,程式碼可以從配置檔案中讀取網路位置,這個配置檔案偶爾會更新。
但是,在現代基於雲的微服務應用中,這是非常難以解決的問題,正如圖4-1顯示的一樣:
服務例項被動態地賦予網路位置。另外,由於自動伸縮、故障和升級,服務例項集合經常會動態改變。所以客戶端程式碼需要使用詳細設計的服務發現機制。
圖4-1 客戶端或者API閘道器需要幫助發現服務
有兩種主要的服務發現機制:客戶端發現機制和服務端發現機制。首先來看一下客戶端發現機制。
二、客戶端發現模式
當使用客戶端發現模式時,客戶端負責確定可用服務例項的網路位置並且對通過它們的請求進行負載均衡。客戶端查詢服務註冊中心,服務註冊中心是一個可用服務例項的資料庫。客戶端接著使用負載均衡演算法選擇可用的服務例項中的一個並把這個請求路由到該例項。
圖4-2顯示這個模式的結構:
圖4-2 客戶端執行服務發現的任務
當服務例項啟動的時候,它的網路地址被註冊到服務註冊中心。當該例項終止的時候,該地址從服務註冊中心移除。服務例項的註冊通常使用心跳機制定期重新整理。
Netflix OSS 為客戶端發現模式提供了很好的例證。Netflix Eureka 是一個服務註冊中心,它提供了REST
API
來管理服務例項的註冊和可用例項的查詢。Netflix Ribbon是一個和Eureka共同工作的IPC
客戶端,它負責將請求負載均衡到可用的服務例項上。後面我們會深入討論Eureka。
客戶端發現模式有很多的缺點和優點。
優點:
- 這個模式相對更直接一點,除了服務註冊中心,沒有要改變的地方;
- 並且,因為客戶端了解可用的服務例項,它能做出智慧、針對特定應用的負載均衡決策,比如使用一致性雜湊。
缺點:
- 這種模式的一個重要的缺陷是它將客戶端與服務註冊中心耦合在一起。你必須為服務客戶端使用的每種程式語言和框架都實現服務發現邏輯;
瞭解了客戶端發現機制,讓我們繼續探索一下服務端發現模式。
三、服務端發現模式
另外一種到服務註冊中心的途徑是服務端發現模式 。圖4-3 顯示了這種模式的結構。
圖4-3 服務註冊中心也可以由伺服器處理
客戶端通過負載均衡器向服務傳送請求。負載均衡器查詢服務註冊中心並路由每個請求到可用的服務例項。與客戶端發現機制一樣,服務例項也需要向服務註冊中心註冊和登出。
AWS Elastic Load Balancer (ELB) 是服務端發現路由器的一個例證。ELB通常用來對外部的因特網流量進行負載均衡。但是,你也可以在內部使用ELB進行到虛擬私有云(virtual private cloud ,VPC)的負載均衡。
客戶端使用ELB的域名來傳送HTTP
或者TCP
請求。ELB將流量負載均衡地路由到一系列註冊的Elastic Compute Cloud (EC2)例項,或者EC2 Container Service (ECS) 容器。不存在獨立可見的服務註冊中心。EC2例項和ECS容器直接註冊到ELB本身。
HTTP伺服器和負載均衡器,比如NGINX Plus和NGINX,也可以用作服務端發現機制中的負載均衡器。例如,這篇文章描述了使用Consul Template動態地更新NGINX反向代理伺服器的配置。Consul Template是一個可以根據儲存在Consul service registry的資料定期重新生成任意配置檔案的工具。無論什麼時候檔案改變,它都會執行任意的shell
命令。在上面的文章中描述的例子中,Consul Template生成了一個nginx.conf的配置檔案,用於配置反向代理,接著執行命令告訴NGINX重新載入該配置檔案。一個更加複雜的實現,比如使用NGINX的HTTP API或者DNS也能動態地更新NGINX Plus的配置 。
一些部署環境,比如Kubernetes和Marathon在叢集的每個主機上都會執行代理。代理扮演服務端發現機制中的負載均衡器的角色。為了給服務發請求,客戶端通過代理使用主機IP和服務的埠號路由請求。代理接著轉發該請求到執行在叢集上的可用服務例項。
服務端發現模式有幾個優點和缺點。
優點:
- 服務發現的細節從客戶端抽象出來,客戶端只需要給負載均衡器發請求即可。這種方式避免為服務客戶端使用的每種程式語言和框架都實現服務發現邏輯;
- 正如上文所說,一些部署環境免費提供了這種功能;
缺點:
- 除非部署環境提供負載均衡器,否則它又是另一個需要設定和管理的高度可用的系統元件;
四、服務註冊中心
服務註冊中心是服務發現機制中的核心部分。它是一個包含服務例項網路位置的資料庫。服務註冊中心需要高度可用並實時更新。客戶端可以快取從服務註冊中心獲取的網路位置。但是,資訊最終會過期,導致客戶端不能發現服務例項。於是,服務註冊中心可以使用複製協議來維護一致性的伺服器叢集。
上文提到,Netflix Eureka是服務註冊中心的很好的例證。它提供REST
API
來註冊和查詢服務例項。服務例項通過POST
請求來註冊它的網路地址,每隔30s,它都要通過PUT
請求來重新整理它的註冊資訊。當服務例項傳送HTTP 的DELETE
請求,或者註冊(包括重新整理)超時的時候,該註冊資訊都會從服務註冊中心移除。如你所想,客戶端可以通過使用HTTP
的GET
請求來獲取已經註冊的服務例項。
Netflix通過在每個Amazon EC2可用區域執行一個或者多個Eureka伺服器來實現高可用性。每個Eureka伺服器執行在有彈性IP地址的EC2例項上。使用DNS
的TEXT
記錄來儲存Eureka叢集的配置,這個配置是從可用區域到Eureka伺服器的網路地址的列表的對映表,當Eureka伺服器啟動的時候,它查詢DNS
來獲取Eureka叢集配置,定位它的夥伴,分配給自己一個沒有使用的彈性IP地址。
Eureka客戶端、服務和服務客戶端通過查詢DNS
來發現Eureka伺服器的網路地址。客戶端更希望使用在相同可用區域裡的Eureka伺服器。但是,如果沒有可用的,就需要使用別的可用區域的裡的Eureka伺服器。
服務註冊中心的其他例子:
- etcd:高度可用,分散式,一致性的鍵值儲存,用來共享配置或作為服務註冊中心。Kubernetes和Cloud Foundry 這兩個著名的專案使用了它;
- Consul:一個發現和配置服務的工具,提供了API允許客戶端註冊並發現服務,也能通過健康檢查來確定服務的可用性;
- Apache ZooKeeper:用於分散式應用的廣泛使用的、高效能的協調服務。開始作為Hadoop的子專案,但是現在是一個獨立的頂級專案;
正如前面提到的,一些系統,比如Kubernetes,Marathon和AWS不需要顯式的服務註冊中心,而是作為基礎設施的內建的一部分。
我們已經瞭解了服務註冊中心的概念,繼續看看服務例項是如何註冊到服務註冊中心的。
五、服務註冊選項
如上所述,服務例項必須從服務註冊中心註冊和登出。有很多種方式可以處理註冊和登出操作:
首先看一下自我註冊模式。
5.1自我註冊模式
當使用自我註冊模式時,服務例項自己負責從服務註冊中心註冊和登出。並且如果必要的話,服務例項要傳送心跳請求來防止註冊過期。圖4-4顯示了這種模式的結構:
圖4-4 服務可以自己完成註冊
這種方法的一個例證是Netflix OSS Eureka client 。Eureka client可以處理服務例項註冊和登出的所有方面的事情。Spring Cloud project 實現了多種模式,包括服務註冊中心,使得自動註冊服務例項到Eureka很容易。你只要在Java
配置類中新增@EnableEurekaClient
註解即可。
自我註冊模式也有很多優點和缺點。
優點:
- 相對簡單,並且不要求額外的系統元件;
缺點:
- 將服務例項和服務註冊中心耦合,導致為服務使用的每種程式語言和框架都實現服務註冊邏輯;
可以替代的方法是第三方註冊模式,它將服務和服務註冊中心解耦,
5.2第三方註冊模式
當使用第三方註冊模式時,服務例項不負責註冊自己到服務註冊中心。 而是通過其他稱為服務註冊元件的系統元件來處理服務註冊。服務註冊元件通過輪詢部署環境或者訂閱事件來追蹤執行例項的集合的變化。當它注意到有新的可用的服務例項時,就會將該例項註冊到服務註冊中心。服務註冊元件也可以登出終止的服務例項。
圖4-5 顯示了這種模式的結構:
圖4-5 獨立的註冊元件服務負責註冊其他的服務
服務註冊元件的一個例證是開源的Registrator工程。它會自動的註冊和登出部署為Docker容器的服務例項。註冊元件支援多種服務註冊中心,比如etcd和Consul。
另外一個服務註冊中心的例證是NetflixOSS Prana 。主要用於非JVM
語言編寫的服務,它是一個和服務例項並行執行的sidecar應用。Prana使用Netflix Eureka來註冊和登出服務例項。
服務註冊元件在一些部署環境中是內建的元件。由Autoscaling Group 建立的EC2例項可以自動的註冊到ELB。Kubernetes 服務會自動註冊並被發現可用。
第三方註冊模式也有很多的缺點和優點。
優點:
- 一個主要的優點是服務與服務註冊中心解耦,不需要為服務使用的每種程式語言和框架都實現服務註冊邏輯。服務註冊邏輯通過一個專門的服務以集中的方式處理;
缺點:
- 除非該註冊元件在部署環境中內建,需要設定和管理一個高可用的系統元件;
六、總結
在微服務架構中,執行的服務例項集合是動態變化的。例項也被動態的賦予網路地址。於是為了客戶端能夠給服務傳送請求,就必須使用服務發現機制。
服務發現機制中的核心部分是服務註冊中心。服務註冊中心是可用服務例項的資料庫。服務註冊中心提供管理API
和查詢API
。服務例項使用管理API
從服務註冊中心註冊和登出。系統元件使用查詢API
來發現可用的服務例項。
服務從服務註冊中心註冊和登出有兩種方式:
在一些部署環境中,需要使用比如Netflix Eureka, etcd, 或者Apache ZooKeeper等設定自己的服務發現基礎設施。在一些其他的部署環境中,服務發現機制是內建的。例如,Kubernetes和Marathon自己處理服務的註冊和登出。它們也在每個叢集主機上執行一個代理,這個叢集主機扮演了服務端發現機制中的路由器的角色。
HTTP
反向代理和負載均衡器比如NGINX也能用作服務端發現種的負載均衡器。服務註冊中心可以給NGINX推送路由資訊並且優雅的完成配置更新。例如可以使用Consul Template。NGINX Plus 支援更多的配置動態更新機制– 它可以使用DNS
從服務註冊中心拉取有關服務例項的資訊,它也提供了API
來遠端完成配置重構。
相關文章
- 10 張圖搞懂服務註冊發現機制
- 服務發現與負載均衡機制-Service負載
- go語言遊戲服務端開發(三)——服務機制Go遊戲服務端
- 基於Kubernetes服務發現機制的探討Non Service
- Java程式設計技術之淺析SPI服務發現機制Java程式設計
- Oracle服務端驗證機制Oracle服務端
- [翻譯]微服務設計模式 - 5. 服務發現 - 服務端服務發現微服務設計模式服務端
- 《springcloud 四》服務保護機制SpringGCCloud
- go語言遊戲服務端開發(四)——RPC機制Go遊戲服務端RPC
- 事務機制如何實現
- Docker實現服務發現Docker
- NodeJs服務註冊與服務發現實現NodeJS
- Casper 機制的歷史起源-第四篇
- 微服務之Eureka服務發現微服務
- 2-服務發現
- go微服務系列(二) - 服務註冊/服務發現Go微服務
- etcd實現服務發現
- Zookeeper實現服務註冊/發現
- 服務發現-從原理到實現
- 小白入門微服務(4) – 服務註冊與服務發現微服務
- 小白入門微服務(4) - 服務註冊與服務發現微服務
- Istio 技術與實踐01: 原始碼解析之 Pilot 多雲平臺服務發現機制原始碼
- 微服務4:服務註冊與發現微服務
- 【微服務之Eureka服務註冊發現】微服務
- consul服務註冊與服務發現的巨坑
- 微服務之服務註冊和服務發現篇微服務
- ZooKeeper服務發現客戶端客戶端
- Nacos服務註冊與發現
- Eureka實現服務註冊與發現
- 微服務~Eureka實現的服務註冊與發現及服務之間的呼叫微服務
- 實現一個“計劃任務”機制
- .Net Core微服務——服務發現:Consul(一)微服務
- .Net Core微服務——服務發現:Consul(二)微服務
- 聊聊微服務的服務註冊與發現!微服務
- 【SpringCloud】(二):服務發現和服務註冊SpringGCCloud
- 微服務架構中的服務發現策略微服務架構
- 如何在Java服務中實現自動化的健康檢查與自愈機制Java
- HBase 事務和併發控制機制原理