1. 程式人生 > >微服務實戰(四):服務發現的可行方案以及實踐案例

微服務實戰(四):服務發現的可行方案以及實踐案例

mesos aws ec2 動態配置 load 顯示 一個 cer c118 分布

微服務實戰(四):服務發現的可行方案以及實踐案例

這是關於使用微服務架構創建應用系列的第四篇文章。第一篇介紹了微服務架構的模式,討論了使用微服務架構的優缺點。第二和第三篇描述了微服務架構內部的通訊機制。這篇文章中,我們將會探討服務發現相關問題。

為什麽要使用服務發現?

設想一下,我們正在寫代碼使用了提供REST API或者Thrift API的服務,為了完成一次服務請求,代碼需要知道服務實例的網絡位置(IP地址和端口)。傳統應用都運行在物理硬件上,服務實例的網絡位置都是相對固定的。例如,代碼可以從一個經常變更的配置文件中讀取網絡位置。

而對於一個現代的,基於雲微服務的應用來說,這卻是一個很麻煩的問題。其架構如圖所示:
技術分享圖片

服務實例的網絡位置都是動態分配的,而且因為擴展、失效和升級等需求,服務實例會經常動態改變,因此,客戶端代碼需要使用一種更加復雜的服務發現機制。

目前有兩大類服務發現模式:客戶端發現服務端發現

我們先來來討論一下客戶端發現。

客戶端發現模式

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

下圖顯示的是這種模式的架構圖:
技術分享圖片
服務實例的網絡位置是在啟動時註冊到服務註冊表中,並且在服務終止時從註冊表中刪除。服務實例註冊信息一般是使用心跳機制來定期刷新的。

Netflix OSS提供了一種非常棒的客戶端發現模式。Netflix Eureka是一個服務註冊表,為服務實例註冊管理和查詢可用實例提供了REST API接口。Netflix Ribbon是一種IPC客戶端,與Eureka合同工作實現對請求的負載均衡。我們會在後面詳細討論Eureka。

客戶端發現模式也是優缺點分明
。這種模式相對比較直接,而且除了服務註冊表,沒有其它改變的因素。除此之外,因為客戶端知道可用服務註冊表信息,因此客戶端可以通過使用哈希一致性(hashing consistently)變得更加聰明,更加有效的負載均衡。

而這種模式一個最大的缺點是需要針對不同的編程語言註冊不同的服務,在客戶端需要為每種語言開發不同的服務發現邏輯。

我們分析過客戶端發現後,再看看服務端發現。

服務端發現模式

另外一種服務發現的模式是服務端發現模式(server-side discovery pattern),下圖展現了這種模式的架構圖:
技術分享圖片
客戶端通過負載均衡器向某個服務提出請求,負載均衡器向服務註冊表發出請求,將每個請求轉發往可用的服務實例。跟客戶端發現一樣,服務實例在服務註冊表中註冊或者註銷


AWS Elastic Load Balancer(ELB)是一種服務端發現路由的例子,ELB一般用於均衡從網絡來的訪問流量,也可以使用ELB來均衡VPC內部的流量。客戶端使用DNS,通過ELB發出請求(HTTP或者TCP)。ELB負載均衡器負責在註冊的EC2實例或者ECS容器之間均衡負載,並不存在一個分離的服務註冊表,而EC2實例和ECS實例也向ELB註冊。

HTTP服務和類似NGINX和NGINX Plus的負載均衡器都可以作為服務端發現均衡器。例如,這篇博文就描述如何使用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請求註冊網絡地址,每30秒必須使用PUT方法更新註冊表,使用HTTP DELETE請求或者實例超時來註銷。可以想見,客戶端可以使用HTTP GET請求接受註冊服務實例信息。

Netflix通過在每個AWS EC2域運行一個或者多個Eureka服務實現高可用性,每個Eureka服務器都運行在擁有彈性IP地址的EC2實例上。DNS TEXT記錄用於存儲Eureka集群配置,其中存放從可用域到一系列Eureka服務器網絡地址的列表。當Eureka服務啟動時,向DNS請求接受Eureka集群配置,確認同伴位置,給自己分配一個未被使用的彈性IP地址。

Eureka客戶端—服務和服務客戶端—向DNS請求發現Eureka服務的網絡地址,客戶端首選使用同一域內的服務。然而,如果沒有可用服務,客戶端會使用另外一個可用域的Eureka服務。

另外一些服務註冊表例子包括:
  • etcd – 是一個高可用,分布式的,一致性的,鍵值表,用於共享配置和服務發現。兩個著名案例包括Kubernetes和Cloud Foundry。
  • consul – 是一個用於發現和配置的服務。提供了一個API允許客戶端註冊和發現服務。Consul可以用於健康檢查來判斷服務可用性。
  • Apache ZooKeeper – 是一個廣泛使用,為分布式應用提供高性能整合的服務。Apache ZooKeeper最初是Hadoop的子項目,現在已經變成頂級項目。

另外,前面強調過,某些系統,例如Kubernetes、Marathon和AWS並沒有獨立的服務註冊表,對他們來說,服務註冊表只是一個內置的功能。

現在我們來看看服務註冊表的概念,看看服務實例是如何在註冊表中註冊的。

服務註冊選項

如前所述,服務實例必須向註冊表中註冊和註銷,如何註冊和註銷也有一些不同的方式。一種方式是服務實例自己註冊,也叫自註冊模式(self-registration pattern);另外一種方式是為其它系統提供服務實例管理的,也叫第三方註冊模式(third party registration pattern)。我們來看看自註冊模式。

自註冊方式

當使用自註冊模式時,服務實例負責在服務註冊表中註冊和註銷。另外,如果需要的話,一個服務實例也要發送心跳來保證註冊信息不會過時。下圖描述了這種架構:
技術分享圖片
一個很好地例子是 Netflix OSS Eureka client。Eureka客戶端負責處理服務實例的註冊和註銷。Spring Cloud project,實現了多種模式,包括服務發現,使得向Eureka服務實例自動註冊時更容易。可以用@EnableEurekaClient註釋Java配置類。

自註冊模式也有優缺點。一個優點是,相對簡單,不需要其他系統功能。而一個主要缺點則是,把服務實例跟服務註冊表聯系起來。必須在每種編程語言和框架內部實現註冊代碼

另外一個方法,不需要連接服務和註冊表,則是第三方註冊模式。

第三方註冊模式

當使用第三方註冊模式時,服務實例並不負責向服務註冊表註冊,而是由另外一個系統模塊,叫做服務管理器,負責註冊。服務管理器通過查詢部署環境或訂閱事件來跟蹤運行服務的改變。當管理器發現一個新可用服務,會向註冊表註冊此服務。服務管理器也負責註銷終止的服務實例。下圖是這種模式的架構圖。
技術分享圖片
一個服務管理器的例子是開源項目Registrator,負責自動註冊和註銷被部署為Docker容器的服務實例。Reistrator支持多種服務管理器,包括etcd和Consul。

另外一個服務管理器例子是NetflixOSS Prana,主要面向非JVM語言開發的服務,也稱為附帶應用(sidecar application),Prana使用Netflix Eureka註冊和註銷服務實例。

服務管理器是部署環境內置的模塊。有自動擴充組創建的EC2實例可以自向ELB自動註冊,Kubernetes服務自動註冊並且對發現服務可用。

第三方註冊模式也是優缺點都有。主要的優點是服務跟服務註冊表是分離的,不需要為每種編程語言和架構完成服務註冊邏輯,替代的,服務實例是通過一個集中化管理的服務進行管理的。

一個缺點是,除非這種服務被內置於部署環境中,否則也需要配置管理一個高可用的系統。

總結

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

服務發現關鍵部分是服務註冊表,也就是可用服務實例的數據庫。服務註冊表提供一種註冊管理API和請求API。服務實例使用註冊管理API來實現註冊和註銷。

請求API用於發現可用服務實例,相對應的,有兩種主要服務發現模式:客戶端發現和服務端發現。

在使用客戶端發現的系統中,客戶端向服務註冊表發起請求,選擇可用實例,然後發出服務請求

而在使用服務端發現的系統中,客戶端通過路由轉發請求,路由器向服務註冊表發出請求,轉發此請求到某個可用實例。

服務實例註冊和註銷主要有兩類方式。一種是服務實例自動註冊到服務註冊表中,也就是自註冊模式;另外一種則是某個系統模塊負責處理註冊和註銷,也就是第三方註冊模式

在某些部署環境中,需要配置自己的服務發現架構,例如:Netflix Eureka、etcd或者Apache ZooKeeper。而在另外一些部署環境中,則自帶了這種功能,例如Kubernetes和Marathon 負責處理服務實例的註冊和註銷。他們也在每個集群節點上運行代理,來實現服務端發現路由器的功能。

HTTP反向代理和負載據衡器(例如NGINX)可以用於服務發現負載均衡器。服務註冊表可以將路由信息推送到NGINX,激活一個實時配置更新;例如,可以使用 Consul Template。NGINX Plus 支持額外的動態重新配置機制,可以使用DNS,將服務實例信息從註冊表中拉下來,並且提供遠程配置的API。

在未來的博客中,我們還將深入探討微服務其它特點。可以註冊NGINX郵件列表來獲得最新產品更新提示。

此篇其它博客譯文參見如下地址:
  • 微服務架構的優勢與不足
  • 使用API Gateway
  • 深入微服務架構的進程間通信

原文鏈接:Service Discovery in a Microservices Architecture (翻譯:楊峰 校對:宋喻)

微服務實戰(四):服務發現的可行方案以及實踐案例