微服務中的服務發現

原文鏈接:Service Discovery in a Microservices Architecture

  1. 微服務介紹
  2. 構建微服務之使用API網關
  3. 構建微服務之:微服務架構中的進程間通信
  4. 微服務中的服務發現(本文)
  5. 微服務之事件驅動的數據管理
  6. 選擇一種微服務部署策略
  7. 重構單體應用到微服務

這是使用微服務構建應用的第四篇文章。第一篇文章介紹了微服務架構模式并討論了使用微服務的優勢和劣勢,該系列的第二和第三篇文章 描述了微服務架構中通信的不同方面,本篇文章我們將密切討論下服務發現的問題。

為什么使用服務發現

設想下,我們寫了一些通過REST API或者Thrift API調用某個服務的代碼,為了發起這個請求,你的代碼需要知道服務實例的網絡地址(IP 地址和端口號)。在傳統運行在物理機器上的應用中,某個服務實例的網絡地址一般是靜態的,比如,代碼可以從只會偶爾更新的配置文件中讀取網絡地址。
然而在現在流行的基于云平臺的微服務應用中, 有更多如下圖所示的困難問題需要去解決:

Paste_Image.png

服務實例需要動態分配網絡地址,而且,一組服務實例可能會因為自動擴展、失敗或者升級發生動態變化,因此 你的客戶端代碼應該使用更加精細的服務發現機制。
有兩種主要的服務發現機制:客戶端發現服務端發現。讓我們先看客戶端發現機制。

客戶端發現模式

當我們使用 客戶端發現的時候,客戶端負責決定可用服務實例的網絡地址并且在集群中對請求負載均衡, 客戶端訪問服務登記表,也就是一個可用服務的數據庫,然后客戶端使用一種負載均衡算法選擇一個可用的服務實例然后發起請求。
下圖展示了該結構模式:

Paste_Image.png

服務實例的網絡地址在服務啟動的時候被登記到服務注冊表中 ,當實例終止服務時從服務注冊表中移除。服務實例的注冊一般是通過心跳機制階段性的進行刷新。

Netflix OSS 為客戶端發現機制提供了很多優秀的例子。Netflix Eureka 實現了服務注冊表,它通過提供REST API來管理服務實例注冊以及可用實例的查詢。Netflix Ribbon 是一個與Eureka一起使用并在多個可用實例間對請求負載均衡的IPC客戶端。我們將在下面文章深入討論Eureka。

客戶端發現機制有諸多優勢和劣勢:該模式除了服務注冊表之外沒有其他的活動部分了,相對來說還是簡單直接的,而且,由于客戶端知道相關的可用服務實例,那么就可以使用更加智能的,特定于應用的負載均衡機制,比如一致性哈希。一個明顯的缺點是它把客戶端與服務注冊表緊耦合了,你必須為每一種消費服務的客戶端對應的編程語言和框架實現服務發現邏輯。

現在看完了客戶端發現,再讓我們看下服務端發現吧。

服務端發現模式

服務發現的另一種模式就是服務端發現模式。下圖展示了該模式的結構:

Paste_Image.png

客戶端通過一個負載均衡器向服務發送請求,負載均衡器查詢服務注冊表并把請求路由到一臺可用的服務實例上。和客戶端發現一樣,服務實例通過服務注冊表進行服務的注冊和注銷。

AWS Elastic Load Balancer (ELB) 是服務端發現路由的一個示例。一個ELB通常對來自外部互聯網的請求進行負載均衡,當然,你也可以使用ELB對虛擬私有云(VPC)的內部請求進行負載均衡。客戶端通過DNS域名向ELB發起HTTP或者TCP請求,ELB將請求負載均衡到一系列注冊的Elastic Compute Cloud (EC2) 實例 或者EC2 Container Service (ECS) 的容器中,兩者并沒有分割的服務注冊表,EC2 實例和ECS容器都是通過ELB進行注冊的。

類似NGINX PLUG和NGINX這些HTTP服務器和負載均衡器可以作為服務端發現負載均衡來使用。比如 這篇博客 就描述了使用Consul Template 動態重配置NGINX反向代理,Consul Template是一種根據存儲在Consul 服務注冊表的配置數據階段性重新生成任意配置文件的工具 ,每當文件發生變化時,它將運行任意的Shell 命令。在博客描述的例子中,Consul Template 生成用于配置反向代理的nginx.conf文件,然后運行一個命令行告知NGINX重載配置。更復雜的實現可能使用 HTTP API or DNS動態重配置NGINX Plus。

一些部署環境使用諸如KubernetesMarathon在集群中的每個主機上運行一個代理,這些代理扮演了服務端發現負載均衡的角色,代理可以根據主機IP地址和服務分配的端口號來路由客戶端請求,代理因此可以透明的把客戶端請求轉發到集群中某臺可用的服務實例上去。

服務端發現模式有一些優勢也有一些劣勢:一個巨大的優勢是,服務發現的細節對客戶端來說是抽象的,客戶端僅需向負載均衡器發送請求即可。這種方式減少了為消費服務的不同編程語言與框架實現服務發現邏輯的麻煩。當然,正如前面所述,一些部署環境已經提供了該功能。這種模式也有一些劣勢: 除非部署環境已經提供了負載均衡器,否則這又是一個需要額外設置和管理的可高可用的系統組件。

服務注冊表

服務注冊表 是服務發現的關鍵部分,它是一個包含服務實例網絡地址的的數據庫。一個服務注冊表需要高可用和實時更新,客戶端可以緩存從服務注冊表獲取的網絡地址。然而,這樣的話緩存的信息最終會過期,客戶端不能再根據該信息發現服務實例。因此,服務注冊表對集群中的服務實例使用復制協議來維護一致性。

之前也提到 Netflix Eureka 是服務注冊表的好例子,它為服務實例的注冊與查詢提供了REST API:一個服務實例可以使用POST來注冊自己的網絡地址,它必須每30秒通過PUT去刷新,服務實例可以直接或者在服務實例注冊超時的時候使用DELETE刪除注冊表中的信息,正如你所料,客戶端可以使用HTTP GET獲取注冊實例的信息。

Netflix通過在每一個Amazon EC2 availability zone運行一到多個Eureka服務 實現高可用 。每一個Eureka服務器運行在一個關聯 Elastic IP地址的 EC2 實例上。DNS TEXT記錄了Eureka集群的配置文件,配置文件映射availability zones到一組Eureka服務器可用的網絡地址。 Eureka 服務器啟動的時候將會查詢DNS獲取Eureka集群的配置、查詢同等節點并為自己分配一個未被使用的Elastic IP地址。

Eureka clients – services和service clients,通過查詢DNS發現Eureka服務器的網絡地址。客戶端更傾向使用在同一availability zone中的Eureka服務器,當然,如果該zone中沒有可用的網絡地址,它將使用另一zone中的。

其他的服務注冊表例子包括:

  • etcd ,一個高可用、分布式、一致性、key-value 方式的存儲,被用在分享配置和服務發現中。兩個著名的項目使用了它:Kubernetes 和 Cloud Foundry.
  • consul ,一個發現和配置服務的工具,為客戶端注冊和發現服務提供了API,Consul還可以通過執行健康檢查決定服務的可用性。
  • Apache Zookeeper ,是一個廣泛使用、高性能的針對分布式應用的協調服務。 Apache Zookeeper本來是Hadoop的子工程,現在已經是頂級工程了。

正如前面所述,一些諸如Kubernetes、Marathon和AWS之類的應用并沒有顯示的服務注冊表,相反,服務注冊表是架構內置的一部分。

我們已經看過了服務注冊表的概念,現在我們看下服務實例是如何使用注冊表注冊的:

服務注冊選項

正如前面提到的那樣,服務實例必須使用服務注冊表來進行服務的注冊和注銷,我們有幾種方式來處理服務的注冊和注銷,其中之一是服務實例自己注冊自己也就是self-registration 模式,另一種是系統的其他組件管理服務實例的注冊,也就是 third-party registration 模式.。我們先看下self-registration模式:

Self-Registration模式

當使用self-registration 模式,時,服務實例自己負責通過服務注冊表對自己進行注冊和注銷,另外如果有必要的話,服務實例可以通過發送心跳請求防止注冊過期,下圖展示了該模式的結構:

Paste_Image.png

Netflix OSS Eureka client就是這種模式的一個例子,Eureka客戶端處理服務實例注冊和注銷的各個方面。Spring Cloud project實現了包括服務發現在內的不同模式,使得自動注冊服務實例到Eureka變的簡單。你可以簡單的在你的java配置類上添加@EnableEurekaClient注解即可。

self-registration模式有一些優勢也有一些劣勢:優勢之一是它相對簡單,而且不強制使用其他的系統組件。然而,一個很大的劣勢是 它使得服務實例和服務注冊表強耦合 ,你必須在每一個使用服務的客戶端編程語言和架構代碼中實現注冊邏輯。

解綁服務和服務注冊表的另一替換方案是,使用third-party registration 模式。

Third-Party Registration模式

當使用third-party registration 模式的時候,服務實例本身并不負責通過服務注冊表注冊自己,相反的,通過另一個被稱作 service registrar系統組件來處理注冊。 service registrar通過輪詢或者訂閱事件來檢測一些運行實例的變化,當它檢測到一個新的可用服務實例時就把該實例注冊到服務注冊表中去,service registrar還負責注銷已經被終止的服務實例,下圖展示了該模式的架構:

Paste_Image.png

service registrar其中一個例子是開源的Registrator 項目,它自動的對部署到Docker 容器中的服務實例進行注冊和注銷。 Registrator支持不同的服務注冊表,包括etcd和Consul。

service registrar的另一個例子是 NetflixOSS Prana,原本是為非JVM語言的服務所設計,它像服務實例的跨斗一樣和服務實例一起運行,Prana使用Netflix Eureka對服務進行注冊和注銷。

service registrar是部署環境的內置組件,EC2實例可以自動擴展組 并可使用ELB進行服務注冊。Kubernetes 服務是自動注冊的并能使其可以被發現。

third-party registration模式有一些優勢也有一些劣勢:主要優勢是使得服務從服務注冊表中被解耦,你不必為開發者使用的每種開發語言和框架實現服務注冊的邏輯,相反,服務實例的注冊被一個專有服務以集中式的方式處理。

該模式的劣勢是,除非它被內置在部署環境中,不然這又是一個需要被設置和管理的高可用系統組件。

總結

在一個微服務應用中,一組運行的服務實例是動態變化的,實例有動態分配的網絡地址,因此,為了使得客戶端能夠向服務發起請求,必須要要有服務發現機制。

服務發現的關鍵是服務注冊表,服務注冊表是可用服務實例的數據庫,它提供了管理和查詢使用的API。服務實例使用這些管理API進行服務的注冊和注銷,系統組件使用查詢API來發現可用的服務實例。

有兩種服務發現的模式:客戶端發現和服務端發現。在使用客戶端發現模式的系統中,客戶端直接查詢服務注冊表,選擇一個可用的實例并發起請求,在一個使用服務端發現模式的系統中,客戶端通過路由發起請求,路由會查詢服務注冊表并把請求轉發到可用的服務實例上。

對服務實例來講有兩種方式可以對服務注冊表進行注冊和注銷,一種是服務實例本身通過服務注冊表來注冊自己,也就是self-registration模式,另一種則是第三方系統組件代表實例來處理服務的注冊和注銷,也就是third-party registration模式。

在一些部署環境中,你需要使用諸如Netflix Eurekaetcd, 或者Apache Zookeeper這樣的服務注冊表來設置你自己的服務發現架構。在另一些部署環境中,服務發現則是內置組件,比如KubernetesMarathon用來處理服務注冊和注銷,他們同樣也在集群的每一個主機上運行一個代理來扮演服務端發現路由的角色。

一些諸如NGINX的HTTP反向代理和負載均衡器 可以用作服務端發現負載均衡器使用,服務注冊表可以向NGINX推送路由信息并調用優雅的配置更新,比如,你可以使用Consul Template。 NGINX Plus 支持額外的動態重配置機制 :它可以使用DNS從服務注冊表 拉取服務實例的信息,并且為遠程重配置提供API。

在該系列之后的文章中我們將繼續挖掘微服務的各個方面。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容