前情概要:微服務化改造系列之一:總覽
服務注冊中心概述
這篇文章是微服務化改造系列的第二篇,主題是服務注冊中心。作為微服務架構最基礎也是最重要的組件之一,服務注冊中心本質上是為了解耦服務提供者和服務消費者。對於任何一個微服務,原則上都應存在或者支持多個提供者,這是由微服務的分布式屬性決定的。更進一步,為了支持彈性擴縮容特性,一個微服務的提供者的數量和分布往往是動態變化的,也是無法預先確定的。因此,原本在單體應用階段常用的靜態LB機制就不再適用了,需要引入額外的組件來管理微服務提供者的注冊與發現,而這個組件就是服務注冊中心。
設計或者選型一個服務注冊中心,首先要考慮的就是服務注冊與發現機制。縱觀當下各種主流的服務注冊中心解決方案,大致可歸為三類:
-
應用內:直接集成到應用中,依賴於應用自身完成服務的注冊與發現,最典型的是Netflix提供的Eureka
-
應用外:把應用當成黑盒,通過應用外的某種機制將服務注冊到注冊中心,最小化對應用的侵入性,比如Airbnb的SmartStack,HashiCorp的Consul
-
DNS:將服務注冊為DNS的SRV記錄,嚴格來說,是一種特殊的應用外注冊方式,SkyDNS是其中的代表
注1:對於第一類注冊方式,除了Eureka這種一站式解決方案,還可以基於ZooKeeper或者Etcd自行實現一套服務注冊機制,這在大公司比較常見,但對於小公司而言顯然性價比太低。
注2:由於DNS固有的緩存缺陷,本文不對第三類注冊方式作深入探討。
除了基本的服務注冊與發現機制,從開發和運維角度,至少還要考慮如下五個方面:
-
測活:服務注冊之后,如何對服務進行測活以保證服務的可用性?
-
負載均衡:當存在多個服務提供者時,如何均衡各個提供者的負載?
-
集成:在服務提供端或者調用端,如何集成注冊中心?
-
運行時依賴:引入注冊中心之后,對應用的運行時環境有何影響?
-
可用性:如何保證注冊中心本身的可用性,特別是消除單點故障?
以下就圍繞上述幾個方面,簡單分析一下Eureka,SmartStack,Consul的利弊。
Eureka
從設計角度來看,Eureka可以說是無懈可擊,注冊中心、提供者、調用者邊界清晰,通過去中心化的集群支持保證了注冊中心的整體可用性,但缺點是Eureka屬於應用內的注冊方式,對應用的侵入性太強,且只支持Java應用。
SmartStack
SmartStack可以說是三種方案中最復雜的,涉及了ZooKeeper、HAProxy、Nerve和Synapse四種異構組件,對運維提出了很高的要求。它最大的好處是對應用零侵入,且適用於任意類型的應用。
Consul
Consul本質上屬於應用外的注冊方式,但可以通過SDK簡化注冊流程。而服務發現恰好相反,默認依賴於SDK,但可以通過Consul Template(下文會提到)去除SDK依賴。
方案
最終我們選擇了Consul作為服務注冊中心的實現方案,主要原因有兩點:
-
最小化對已有應用的侵入性,這也是貫穿我們整個微服務化改造的原則之一
-
降低運維的復雜度,Consul Agent既可以運行在服務器模式,又可以運行在客戶端模式
Consul Template
上文提到使用Consul,默認服務調用者需要依賴Consul SDK來發現服務,這就無法保證對應用的零侵入性。所幸通過Consul Template,可以定時從Consul集群獲取最新的服務提供者列表並刷新LB配置(比如nginx的upstream),這樣對於服務調用者而言,只需要配置一個統一的服務調用地址即可。改造后的調用關系如下:
Spring Cloud Consul
由於我們選用了Spring Boot作為統一的微服務實現框架,很自然的,可以利用Spring Cloud提供的Consul組件進一步簡化服務注冊流程,省去額外的服務提供端的Consul配置。