微服務從設計到部署(四)服務發現

鏈接:https://github.com/oopsguy/microservices-from-design-to-deployment-chinese
譯者:Oopsguy

本書主要介紹如何使用微服務來構建應用程序,現在是第四章。第一章已經介紹了微服務架構模式,並討論了使用微服務的優點與缺點。第二章和第三章介紹了微服務間的通信,並對不同的通信機製作出對比。在本章中,我們將探討服務發現(service discovery)相關的內容。

4.1、爲何使用服務發現

我們假設您正在編寫某些代碼,這些代碼調用了有 REST API 或 Thrift API 的服務。爲了發送一個請求,您的代碼需要知道服務實例的網絡位置(IP 地址與端口)。在運行於物理硬件上的傳統應用中,服務實例的網絡位置是相對靜態的。例如,您的代碼可以從偶爾更新的配置文件中讀取網絡位置。

然而,在現代基於雲的微服務應用中,這是一個更難解決的問題,如圖 4-1 所示。

服務實例具有動態分配的網絡位置。此外,由於自動擴展、故障與升級,整組服務實例會動態變更。因此,您的客戶端代碼需要使用更精確的服務發現機制。

圖 4-1、需要服務尋找幫助的客戶端或 API 網關

有兩種主要的服務發現模式:客戶端發現(client-side discovery)與服務端發現(server-side discovery)。讓我們先來看看客戶端發現。

4.2、客戶端發現模式

當使用客戶端發現模式時,客戶端負責確定可用服務實例的網絡位置和請求負載均衡。客戶端查詢服務註冊中心(service registry),它是可用服務實例的數據庫。之後,客戶端利用負載均衡算法選擇一個可用的服務實例併發出請求。

圖 4-2 展示了該模式的結構

客戶端可以承擔發現服務任務

服務實例的網絡位置在服務註冊中心啓動時被註冊。當實例終止時,它將從服務註冊中心中移除。通常使用心跳機制週期性地刷新服務實例的註冊信息。

Netflix OSS 提供了一個很好的客戶端發現模式示例。Netflix Eureka 是一個服務註冊中心,它提供了一個用於管理服務實例註冊和查詢可用實例的 REST API。Netflix Ribbon 是一個 IPC 客戶端,可與 Eureka 一起使用,用於在可用服務實例之間使請求負載均衡。本章稍後將討論 Eureka。

客戶端發現模式有各種優點與缺點。該模式相對比較簡單,除了服務註冊中心,沒有其他移動部件。此外,由於客戶端能發現可用的服務實例,因此可以實現智能的,特定於應用程序的負載均衡決策,比如使用一致性哈希。該模式的一個重要缺點是它將客戶端與服務註冊中心耦合在一起。您必須爲服務客戶端使用的每種編程語言和框架實現客戶端服務發現邏輯。

現在我們已經瞭解了客戶端發現,接下來讓我們看看服務器端發現。

4.3、服務端發現模式

服務發現的另一種方式是服務端發現模式。圖 4-3 展示了該模式的結構:

服務器間處理也可以處理服務發現

客戶端通過負載均衡器向服務發出請求。負載均衡器查詢服務註冊中心並將每個請求路由到可用的服務實例。與客戶端發現一樣,服務實例由服務註冊中心註冊與銷燬。

AWS Elastic Load Balancer(ELB)是一個服務端發現路由示例。ELB 通常用於負載均衡來自互聯網的外部流量。然而,您還可以使用 ELB 來負載均衡虛擬私有云(VPC)內部的流量。客戶端通過 ELB 使用其 DNS 名稱來發送請求(HTTP 或 TCP)。ELB 負載均衡一組已註冊的 Elastic Compute Cloud(EC2)實例或 EC2 Container Service(ECS)容器之間的流量。這裏沒有單獨可見的服務註冊中心。相反,EC2 實例 與 ECS 容器由 ELB 本身註冊。

HTTP 服務器和負載均衡器(如 NGINX Plus 和 NGINX)也可以作爲服務端發現負載均衡器。例如,此博文描述了使用 Consul Template 動態重新配置 NGINX 反向代理。Consul Template 是一個工具,可以從存儲在 Consul 服務註冊中心中的配置數據中定期重新生成任意配置文件。每當文件被更改時,它都會運行任意的 shell 命令。在列舉的博文描述的示例中,Consul Template 會生成一個 nginx.conf 文件,該文件配置了反向代理,然後通過運行一個命令告知 NGINX 重新加載配置的命令。更復雜的實現可以使用其 HTTP API 或 DNS 動態重新配置 NGINX Plus。

某些部署環境(如 Kubernetes 和 Marathon)在羣集中的每個主機上運行着一個代理。這些代理扮演着服務端發現負載均衡器角色。爲了向服務發出請求,客戶端通過代理使用主機的 IP 地址和服務的分配端口來路由請求。然後,代理將請求透明地轉發到在集羣中某處運行的可用服務實例。

服務端發現模式有幾個優點與缺點。該模式的一個很大的優點是發現的細節從客戶端抽象出來。客戶端只需向負載均衡器發出請求。這消除了爲服務客戶端使用的每種編程語言和框架都實現發現邏輯的必要性。另外,如上所述,一些部署環境免費提供此功能。然而,這種模式存在一些缺點。除非負載均衡器由部署環境提供,否則您需要引入這個高可用系統組件,並進行設置和管理。

4.4、服務註冊中心

服務註冊中心(service registry)是服務發現的一個關鍵部分。它是一個包含了服務實例網絡位置的數據庫。服務註冊中心必須是高可用和最新的。雖然客戶端可以緩存從服務註冊中心獲得的網絡位置,但該信息最終會過期,客戶端將無法發現服務實例。因此,服務註冊中心由使用了複製協議(replication protocol)來維護一致性的服務器集羣組成。

如之前所述,Netflix Eureka 是一個很好的服務註冊中心範例。它提供了一個用於註冊和查詢服務實例的 REST API。服務實例使用 POST 請求註冊其網絡位置。它必須每隔 30 秒使用 PUT 請求來刷新其註冊信息。通過使用 HTTP DELETE 請求或實例註冊超時來移除註冊信息。正如您所料,客戶端可以使用 HTTP GET 請求來檢索已註冊的服務實例。

Netflix 通過在每個 Amazon EC2 可用性區域(Availability Zone)中運行一個或多個 Eureka 服務器來實現高可用。每個 Eureka 服務器都運行在具有一個 Elastic IP 地址的 EC2 實例上。DNS TEXT 記錄用於存儲 Eureka 集羣配置,這是一個從可用性區域到 Eureka 服務器的網絡位置列表的映射。當 Eureka 服務器啓動時,它將會查詢 DNS 以檢索 Eureka 羣集配置,查找其對等體,併爲其分配一個未使用的 Elastic IP 地址。

經過 Eureka 客戶端 - 服務與服務客戶端 - 查詢 DNS 以發現 Eureka 服務器的網絡位置。客戶端優先使用相同可用性區域中的 Eureka 服務器,如果沒有可用的,則使用另一個可用性區域的 Eureka 服務器。

以下列舉了其他服務註冊中心:

  • etcd - 一個用於共享配置和服務發現的高可用、分佈式和一致的鍵值存儲。使用 etcd 的兩個著名項目分別爲 Kubernetes 和 Cloud Foundry。
  • Consul - 一個發現與配置服務工具。它提供了一個 API,可用於客戶端註冊與發現服務。Consul 可對服務進行健康檢查,以確定服務的可用性。
  • Apache ZooKeeper - 一個被廣泛應用於分佈式應用程序的高性能協調服務。Apache ZooKeeper 最初是一個 Hadoop 子項目,但現在已經成爲一個獨立的頂級項目。

另外,如之前所述,部分系統,如 Kubernetes、Marathon 和 AWS,沒有明確的服務註冊中心。相反,服務註冊中心只是基礎設施的一個內置部分。
 
現在我們已經瞭解服務註冊中心的概念,接下來讓我們看看服務實例是如何被註冊到服務註冊中心。

4.5、服務註冊方式

如之前所述,服務實例必須在服務註冊中心中註冊與註銷。有幾種不同的方式來處理註冊和註銷。一是服務實例自我註冊,即自注冊模式。另一個是使用其他系統組件來管理服務實例的註冊,即第三方註冊模式。我們先來了解自注冊模式。

4.6、自注冊模式

當使用自注冊模式時,服務實例負責在服務註冊中心註冊和註銷自己。此外,如果有必要,服務實例將通過發送心跳請求來防止其註冊信息過期。

圖 4-4 展示了該模式的結構。

圖 4-4、服務可以自我處理註冊

該方式的一個很好的範例就是 Netflix OSS Eureka 客戶端。Eureka 客戶端負責處理服務實例註冊與註銷的所有方面。實現了包括服務發現在內的多種模式的 Spring Cloud 項目可以輕鬆地使用 Eureka 自動註冊服務實例。您只需在Java Configuration類應用 @EnableEurekaClient 註解即可。

自注冊模式有好有壞。一個好處是它相對簡單,不需要任何其他系統組件。然而,主要缺點是它將服務實例與服務註冊中心耦合。您必須爲服務使用的每種編程語言和框架都實現註冊代碼。

將服務與服務註冊中心分離的替代方法是第三方註冊模式。

4.7、第三方註冊模式

當使用第三方註冊模式時,服務實例不再負責向服務註冊中心註冊自己。相反,該工作將由被稱爲服務註冊器(service registrar)的另一系統組件負責。服務註冊器通過輪詢部署環境或訂閱事件來跟蹤運行實例集的變更情況。當它檢測到一個新的可用服務實例時,它會將該實例註冊到服務註冊中心。此外,服務註冊器可以註銷終止的服務實例。

圖 4-5 展示了該模式的結構:

圖 4-5、一個單獨的服務註冊器可負責註冊其他服務

服務註冊器的一個例子是開源的 Registrator 項目。它可以自動註冊和註銷作爲 Docker 容器部署的服務實例。註冊器支持多個服務註冊中心,包括 etcd 和 Consul。

服務註冊器的另一個例子是 NetflixOSS Prana。其主要用於非 JVM 語言編寫的服務,它是一個與服務實例並行運行的側中應用。Prana 使用了 Netflix Eureka 來註冊和註銷服務實例。

服務註冊器在部分部署環境中是一個內置組件。Autoscaling Group 創建的 EC2 實例可以自動註冊到 ELB。Kubernetes 服務將自動註冊並提供發現。

第三方註冊模式同樣有好有壞。一個主要的好處是服務與服務註冊中心之間解耦。您不需要爲開發人員使用的每種編程語言和框架都實現服務註冊邏輯。相反,僅需要在專用服務中以集中的方式處理服務實例註冊。

該模式的一個缺點是,除非部署環境內置,否則您同樣需要引入這樣的一個高可用的系統組件,並進行設置和管理。

4.8、總結

在微服務應用程序中,運行的服務實例集會動態變更。實例具有動態分配的網絡位置。因此,爲了讓客戶端向服務發出請求,它必須使用服務發現機制。

服務發現的一個關鍵部分是服務註冊中心。服務註冊中心是一個可用服務實例的數據庫。服務註冊中心提供了管理 API 和查詢 API 的功能。服務實例通過使用管理 API 從服務註冊中心註冊或者註銷。系統組件使用查詢 API 來發現可用的服務實例。

有兩種主要的服務發現模式:客戶端發現與服務端發現。在使用了客戶端服務發現的系統中,客戶端查詢服務註冊中心,選擇一個可用實例併發出請求。在使用了服務端發現的系統中,客戶端通過路由器進行請求,路由器將查詢服務註冊中心,並將請求轉發到可用實例。

服務實例在服務註冊中心中註冊與註銷有兩種主要方式。一個是服務實例向服務注中心自我註冊,即自注冊模式。另一個是使用他系統組件代表服務完成註冊與註銷,即第三方註冊模式。

在某些部署環境中,您需要使用如 Netflix Eureka 或 Apache ZooKeeper 等服務註冊中心來設置您自己的服務發現基礎設施。在其他部署環境中,服務發現是內置的,例如,Kubernetes 和 Marathon,可以處理服務實例的註冊與註銷。他們還在每一個扮演服務端發現路由器角色的集羣主機上運行一個代理。

一個 HTTP 反向代理和負載均衡器(如 NGINX)也可以用作服務端發現負載均衡器。服務註冊中心可以將路由信息推送給 NGINX,並調用一個正常的配置更新;例如,您可以使用 Consul Template。NGINX Plus 支持額外的動態重新配置機制 - 它可以使用 DNS 從註冊中心中提取有關服務實例的信息,併爲遠程重新配置提供一個 API。

微服務實戰:NGINX 的靈活性

by Floyd Smith

在微服務環境中,由於自動擴展、故障和升級,您的後端基礎設施可能會不斷變化,這些包括了服務的創建,部署和擴展。如本章所述,在動態重新分配服務位置的環境中需要服務發現機制。

將 NGINX 應用於微服務的一部分好處是,您可以輕鬆地將其配置爲自動響應後端基礎設施作出的變更。NGINX 配置不僅簡單靈活,而且兼容 Amazon Web Services 使用的模板,可以更輕鬆地管理特定的服務變更與受負載均衡的變更服務組。

NGINX Plus 具有即時重新配置 API,無需重新啓動 NGINX Plus 或手動重新加載配置就能感知受負載均衡服務組的變更。在 NGINX Plus Release 8 及更高版本中,您可以將對 API 所做的更改配置爲在重新啓動和配置重新加載時保持不變。(重新加載不需要重新啓動,不要斷開連接)NGINX Plus Release 9 及更高版本支持使用 DNS SRV 記錄進行服務發現,可與現有服務器發現平臺(如 Consul 和 etcd)進行更緊密地集成。

我們在 NGINX 創建了一個用於管理服務發現的模型:

  1. 爲幾個應用程序單獨運行的Docker容器,包括如 etcd 的服務發現應用程序、服務註冊工具、一個或多個後端服務器以及用於負載均衡其他容器的 NGINX Plus 本身。
  2. 註冊工具監控 Docker 的新容器,並使用服務發現工具註冊新服務,此外,還可以刪除消失的容器。
  3. 容器及其運行的服務將自動添加到負載均衡上游服務器中或從其中刪除。

此 Demo 應用程序可用於多個服務發現應用程序:Consul API、來自 Consul 的 DNS SRV 記錄、etcd 以及 ZooKeeper 等。

本系列全部譯文

  • https://github.com/oopsguy/microservices-from-design-to-deployment-chinese

相關鏈接

  • 微服務從設計到部署(一)微服務簡介
  • 微服務從設計到部署(二)使用 API 網關
  • 微服務從設計到部署(三)進程間通信
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章