「Chris Richardson 微服務系列」服務發現的可行方案以及實踐案例-4(轉)

「Chris Richardson 微服務系列」服務發現的可行方案以及實踐案例

編者的話|本文來自 Nginx 官方博客,是微服務系列的第四篇文章。第一篇介紹了微服務架構的模式,討論了使用微服務架構的優缺點;第二篇和第三篇描述了微服務架構內部的通訊機制。這篇文章中,我們將會探討服務發現。

 轉自http://blog.daocloud.io/microservices-4/

作者介紹:Chris Richardson,是世界著名的軟件大師,經典技術著作《POJOS IN ACTION》一書的作者,也是 cloudfoundry.com 最初的創始人,Chris Richardson 與 Martin Fowler、Sam Newman、Adrian Cockcroft 等並稱爲世界十大軟件架構師。

0516_richardson_服務

Chris Richardson 微服務系列全 7 篇:

1. 微服務架構概念解析

2. 構建微服務架構:使用 API Gateway

3. 深入微服務架構的進程間通信(本篇文章)

4. 服務發現的可行方案以及實踐案例

5. 微服務的事件驅動數據管理

6. 選擇微服務部署策略

7. 將單體應用改造爲微服務(本篇文章)

Chris Richardson 所著所有文章已獨家授權 DaoCloud 翻譯並刊載。

本期內容:

爲什麼要使用服務發現?

假設我們寫的代碼會調用 REST API 或者 Thrift API 的服務。爲了完成一次請求,代碼需要知道服務實例的網絡位置(IP 地址和端口)。運行在物理硬件上的傳統應用中,服務實例的網絡位置是相對固定的;代碼能從一個偶爾更新的配置文件中讀取網絡位置。

對於基於雲端的、現代化的微服務應用而言,這卻是一大難題,正如下圖所示。

Richardson-microservices-part4-1_difficult-service-discovery

服務實例的網絡位置都是動態分配的。由於擴展、失敗和升級,服務實例會經常動態改變,因此,客戶端代碼需要使用更加複雜的服務發現機制。

服務發現有兩大模式:客戶端發現模式和服務端發現模式。我們先來了解客客戶端發現模式。

客戶端發現模式

使用客戶端發現模式時,客戶端決定相應服務實例的網絡位置,並且對請求實現負載均衡。客戶端查詢服務註冊表,後者是一個可用服務實例的數據庫;然後使用負載均衡算法從中選擇一個實例,併發出請求。

客戶端從服務註冊服務中查詢,其中是所有可用服務實例的庫。客戶端使用負載均衡算法從多個服務實例中選擇出一個,然後發出請求。

下圖顯示了這種模式的架構:

Richardson-microservices-part4-2_client-side-pattern

服務實例的網絡位置在啓動時被記錄到服務註冊表,等實例終止時被刪除。服務實例的註冊信息通常使用心跳機制來定期刷新。

Netflix OSS 是客戶端發現模式的絕佳範例。Netflix Eureka 是一個服務註冊表,爲服務實例註冊管理和查詢可用實例提供了 REST API 接口。Netflix Ribbon 是 IPC 客戶端,與 Eureka 一起實現對請求的負載均衡。我們會在後面深入討論 Eureka。

客戶端發現模式優缺點兼有。這一模式相對直接,除了服務註冊外,其它部分無需變動。此外,由於客戶端知曉可用的服務實例,能針對特定應用實現智能負載均衡,比如使用哈希一致性。這種模式的一大缺點就是客戶端與服務註冊綁定,要針對服務端用到的每個編程語言和框架,實現客戶端的服務發現邏輯。

分析過客戶端發現後,我們來了解服務端發現。

服務端發現模式

另外一種服務發現的模式是服務端發現模式,下圖展現了這種模式的架構:

Richardson-microservices-part4-3_server-side-pattern

客戶端通過負載均衡器向某個服務提出請求,負載均衡器查詢服務註冊表,並將請求轉發到可用的服務實例。如同客戶端發現,服務實例在服務註冊表中註冊或註銷。

AWS Elastic Load Balancer(ELB)是服務端發現路由的例子,ELB 通常均衡來自互聯網的外部流量,也可用來負載均衡 VPC(Virtual private cloud)的內部流量。客戶端使用 DNS 通過 ELB 發出請求(HTTP 或 TCP),ELB 在已註冊的 EC2 實例或 ECS 容器之間負載均衡。這裏並沒有單獨的服務註冊表,相反,EC2 實例和 ECS 容器註冊在 ELB。

HTTP 服務器與類似 NGINX PLUS 和 NGINX 這樣的負載均衡起也能用作服務端的發現均衡器。Graham Jenson 的 Scalable Architecture DR CoN: Docker, Registrator, Consul, Consul Template and Nginx 一文就描述如何使用 Consul Template 來動態配置 NGINX 反向代理。Consul Template 定期從 Consul Template 註冊表中的配置數據中生成配置文件;文件發生更改即運行任意命令。在這篇文章中,Consul Template 生成 nginx.conf 文件,用於配置反向代理,然後運行命令,告訴 NGINX 重新加載配置文件。在更復雜的實現中,需要使用 HTTP API 或 DNS 來動態配置 NGINX Plus。

Kubernetes 和 Marathon 這樣的部署環境會在每個集羣上運行一個代理,將代理用作服務端發現的負載均衡器。客戶端使用主機 IP 地址和分配的端口通過代理將請求路由出去,向服務發送請求。代理將請求透明地轉發到集羣中可用的服務實例。

服務端發現模式兼具優缺點。它最大的優點是客戶端無需關注發現的細節,只需要簡單地向負載均衡器發送請求,這減少了編程語言框架需要完成的發現邏輯。並且如上文所述,某些部署環境免費提供這一功能。這種模式也有缺點。除非負載均衡器由部署環境提供,否則會成爲一個需要配置和管理的高可用系統組件。

服務註冊表

服務註冊表是服務發現的核心部分,是包含服務實例的網絡地址的數據庫。服務註冊表需要高可用而且隨時更新。客戶端能夠緩存從服務註冊表中獲取的網絡地址,然而,這些信息最終會過時,客戶端也就無法發現服務實例。因此,服務註冊表會包含若干服務端,使用複製協議保持一致性。

如前所述,Netflix Eureka 是服務註冊表的上好案例,爲註冊和請求服務實例提供了 REST API。服務實例使用 POST 請求來註冊網絡地址,每三十秒使用 PUT 請求來刷新註冊信息。註冊信息也能通過 HTTP DELETE 請求或者實例超時來被移除。以此類推,客戶端能夠使用 HTTP GET 請求來檢索已註冊的服務實例。

Netflix 通過在每個 AWS EC2 域運行一個或者多個 Eureka 服務實現高可用性。每個 Eureka 服務器都運行在擁有彈性 IP 地址的 EC2 實例上。DNS TEXT 記錄被用來保存 Eureka 集羣配置,後者包括可用域和 Eureka 服務器的網絡地址列表。Eureka 服務在啓動時會查詢 DNS 去獲取 Eureka 集羣配置,確定同伴位置,以及給自己分配一個未被使用的彈性 IP 地址。

Eureka 客戶端,包括服務和服務客戶端,查詢 DNS 去發現 Eureka 服務的網絡地址。客戶端首選同一域內的 Eureka 服務。然而,如果沒有可用服務,客戶端會使用其它可用域中的 Eureka 服務。

其它的服務註冊表包括:

  • etcd – 高可用、分佈式、一致性的鍵值存儲,用於共享配置和服務發現。Kubernetes 和 Cloud Foundry 是兩個使用 etcd 的著名項目。
  • consul – 發現和配置的服務,提供 API 實現客戶端註冊和發現服務。Consul 通過健康檢查來判斷服務的可用性。
  • Apache ZooKeeper – 被分佈式應用廣泛使用的高性能協調服務。Apache ZooKeeper 最初是 Hadoop 的子項目,現在已成爲頂級項目。

此外,如前所強調,像 Kubernetes、Marathon 和 AWS 並沒有明確的服務註冊,相反,服務註冊已經內置在基礎設施中。

瞭解了服務註冊的概念後,現在瞭解服務實例如何在註冊表中註冊。

服務註冊的方式

如前所述,服務實例必須在註冊表中註冊和註銷。註冊和註銷有兩種不同的方法。方法一是服務實例自己註冊,也叫自注冊模式(self-registration pattern);另一種是採用管理服務實例註冊的其它系統組件,即第三方註冊模式。

自注冊方式

當使用自注冊模式時,服務實例負責在服務註冊表中註冊和註銷。另外,如果需要的話,一個服務實例也要發送心跳來保證註冊信息不會過時。下圖描述了這種架構:

Richardson-microservices-part4-4_self-registration-pattern

Netflix OSS Eureka 客戶端是非常好的案例,它負責處理服務實例的註冊和註銷。Spring Cloud 能夠執行包括服務發現在內的各種模式,使得利用 Eureka 自動註冊服務實例更簡單,只需要給 Java 配置類註釋 @EnableEurekaClient。

自注冊模式優缺點兼備。它相對簡單,無需其它系統組件。然而,它的主要缺點是把服務實例和服務註冊表耦合,必須在每個編程語言和框架內實現註冊代碼。

另一個方案將服務與服務註冊表解耦合,被稱作第三方註冊模式。

第三方註冊模式

使用第三方註冊模式,服務實例則不需要向服務註冊表註冊;相反,被稱爲服務註冊器的另一個系統模塊會處理。服務註冊器會通過查詢部署環境或訂閱事件的方式來跟蹤運行實例的更改。一旦偵測到有新的可用服務實例,會向註冊表註冊此服務。服務管理器也負責註銷終止的服務實例。下面是這種模式的架構圖。

Richardson-microservices-part4-5_third-party-pattern

Registrator 是一個開源的服務註冊項目,它能夠自動註冊和註銷被部署爲 Docker 容器的服務實例。Registrator 支持包括 etcd 和 Consul 在內的多種服務註冊表。

NetflixOSS Prana 是另一個服務註冊器,主要面向非 JVM 語言開發的服務,是一款與服務實例一起運行的並行應用。Prana 使用 Netflix Eureka 來註冊和註銷服務實例。

服務註冊器是部署環境的內置組件。由 Autoscaling Group 創建的 EC2 實例能夠自動向 ELB 註冊。Kubernetes 服務自動註冊並能夠被發現。

第三方註冊模式也是優缺點兼具。在第三方註冊模式中,服務與服務註冊表解耦合,無需爲每個編程語言和框架實現服務註冊邏輯;相反,服務實例通過一個專有服務以中心化的方式進行管理。它的不足之處在於,除非該服務內置於部署環境,否則需要配置和管理一個高可用的系統組件。

總結

在微服務應用中,服務實例的運行環境會動態變化,實例網絡地址也是如此。因此,客戶端爲了訪問服務必須使用服務發現機制。

服務註冊表是服務發現的關鍵部分。服務註冊表是可用服務實例的數據庫,提供管理 API 和查詢 API。服務實例使用管理 API 來實現註冊和註銷,系統組件使用查詢 API 來發現可用的服務實例。

服務發現有兩種主要模式:客戶端發現和服務端發現。在使用客戶端服務發現的系統中,客戶端查詢服務註冊表,選擇可用的服務實例,然後發出請求。在使用服務端發現的系統中,客戶端通過路由轉發請求,路由器查詢服務註冊表並轉發請求到可用的實例。

服務實例的註冊和註銷也有兩種方式。一種是服務實例自己註冊到服務註冊表中,即自注冊模式;另一種則是由其它系統組件處理註冊和註銷,也就是第三方註冊模式。

在一些部署環境中,需要使用 Netflix Eureka、etcd、Apache Zookeeper 等服務發現來設置自己的服務發現基礎設施。而另一些部署環境則內置了服務發現。例如,Kubernetes 和 Marathon 處理服務實例的註冊和註銷,它們也在每個集羣主機上運行代理,這個代理具有服務端發現路由的功能。

HTTP 反向代理和 NGINX 這樣的負載均衡器能夠用做服務器端的服務發現均衡器。服務註冊表能夠將路由信息推送到 NGINX,激活配置更新,譬如使用 Cosul Template。NGINX Plus 支持額外的動態配置機制,能夠通過 DNS 從註冊表中獲取服務實例的信息,併爲遠程配置提供 API。

英文原文:https://www.nginx.com/blog/service-discovery-in-a-microservices-architecture/

This entry was posted in 乾貨 and tagged 微服務. Bookmark the permalink.

Post navigation

8 thoughts on “「Chris Richardson 微服務系列」服務發現的可行方案以及實踐案例”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章