面試不再慌!跟著老司機吃透Spring Cloud

歡迎Java工程師關注簡書專欄
Java架構技術進階
本專欄收錄各種Java相關技術,面試題,以及學習感悟,心得!

最近和朋友聊天,提到他前幾天面試的時候被問到:“能否描述一下Spring Cloud?”他當場就懵了,不知道從何說起。

是啊,Spring Cloud 是知名的微服務架構,包含了很多組件,每個組件又有各自的分工。

怎么才能理解 Spring Cloud 架構并且說清楚它到底做了些什么呢?我們今天一起來看一下。

從一個例子開始

對于這樣的“大”問題,通常需要拆解成小問題來回答。要說明 Spring Cloud 做了什么,就要說清楚它包含的組件都做了些什么?

如果一個個把組件羅列出來,似乎太過獨立,沒有關聯(lián)性,缺少邏輯感。我們就從一個簡單的例子開始,把這些組件像串珍珠一樣串起來。

假設有一個項目,這個項目有兩個服務,分別是“A”和“B”:

“A”和“B”的關系是,“A”調用“B”。

然后,有一個客戶端“C”調用“A”。

客戶端“C”調用服務“A”,服務“A”調用服務“B”

Eureka 服務之間互相認識

在服務端我們已經(jīng)有了兩個服務,“A”和“B”。他們的關系是“A”調用“B”,“B”被“A”調用。

當只有兩個服務的時候我們是知道這種關系,并且可以把這種關系記錄下來的,但是如果服務一多,我們如何記錄這種關系呢?

于是,Eureka 就登場了,它負責“服務注冊,服務發(fā)現(xiàn)”的工作。Eureka 分成 Eureka Server 和 Eureka Client。

每個微服務架構都會有一個或者多個 Eureka Server 用來保存注冊服務的信息。

每個服務都會包含一個Eureka Client,其中會配置Eureka Server的信息,這樣當服務啟動的時候就能夠把自己注冊到 Eureka Server 中去了。

同時每個服務也可以通過 Eureka Client 從 Eureka Server 中獲取其他服務的信息(Get Registry)。

“A”服務與“B”服務的調用關系

“A”服務和“B”服務首先通過自身集成的 Eureka Client 到 Eureka Server 上注冊自身的信息,包括:服務名,地址,端口號等等。

注冊完畢以后,“A”服務通過 Eureka Client 從 Eureka Server 獲?。℅et Registry)服務“B”的信息。

由于,“A”服務調用“B”服務,所以“A”服務稱之為“消費者”,“B”服務稱之為“生產(chǎn)者”。

Feign 服務之間信息傳遞

既然“A”“B”兩個服務互相認識了,接下來就要輪到“A”服務調用“B”服務了。

由于兩個是單獨的服務,并且兩個服務都在一個網(wǎng)絡內,通常會通過 HTTP 請求進行調用。

傳統(tǒng)的做法是,“A”服務寫好請求的消息,序列化成二進制的串傳遞給“B”服務,“B”服務收到消息以后反序列化消息進行解析,接著以同樣的方式應答“A”服務。

從傳統(tǒng)意義上完成這些代碼需要大量的工作,而且需要考慮很多編碼上面的問題。為了簡化上面的過程,F(xiàn)eign 組件就誕生了,它方便了服務之間的調用。

引入 Feign 了以后,在“A”服務中只需要填寫簡單的 URL,參數(shù),請求方式,就可以調用“B”服務了。調用“B”服務就好像調用本地的一個方法一樣簡單。

通過 Feign 調用服務的代碼片段

我們需要做的就是在“A”服務(消費者)中建立一個 Feign Client,填寫我們需要調用的 URL,參數(shù)和方式就可以了,其他的事情就交給 Feign 來完成了。

Feign Client 工作流

從上圖可以看出,“消費者”開始只需要提供“生產(chǎn)者”的 URL,參數(shù)等信息。

Feign Client 會根據(jù)這些信息生成對應的 HTTP 請求頭和報文,然后發(fā)送給生產(chǎn)者。

生產(chǎn)者返回信息以后,F(xiàn)eign Client 同樣會返回“消費者”能夠讀懂的 JavaBean 的信息。

Ribbon 搞定負載均衡

好了,現(xiàn)在“A”“B”服務互相認識了,并且“A”服務可以調用“B”服務了。

假設“B”服務的業(yè)務量增大,一個“B”服務無法滿足現(xiàn)在的要求,另外又復制了兩個“B”服務,連同原來的一個“B”服務,現(xiàn)在一共有三個“B”服務。

雖然三個提供的服務都是一樣的,但是“A”服務應該調用哪個“B”服務的復制呢?

這時 Ribbon 就登場了,它用來做負載均衡?!癆”服務無需知道調用三個復制中的哪一個,它只用告訴 Ribbon 我要調用“B”服務,Ribbon 會根據(jù)策略去調用三個復制中的某一個。

Ribbon 充當負載均衡器的角色

在 Ribbon 的幾種負載均衡策略中,隨機策略是用的比較多的。例如:“B1”,“B2”,“B3”分別是“B”服務的三個復制。

“A”服務第一次,調用的是“B1”服務,根據(jù)隨機策略,第二次就訪問“B2”服務,第三次訪問“B3”服務,第四次又訪問“B1”服務,依次類推,循環(huán)往復。

下面列出其他幾個服務僅供參考,篇幅有限不做贅述:

  • 隨機(Random)
  • 輪詢(RoundRobin)
  • 一致性哈希(ConsistentHash)
  • 哈希(Hash)
  • 加權(Weighted)

Hystrix 服務出現(xiàn)故障

現(xiàn)在“A”服務知道如何調用“B1”,“B2”,“B3”三個“B”服務的復制了。

假如“B2”服務出現(xiàn)故障,“A”服務還可以訪問它嗎?為了避免單個服務的故障影響到其他服務,Hystrix 就應運而生了。

調用“B1”服務失敗

Hystrix 俗稱熔斷器(斷路器),當服務不可用或者出現(xiàn)故障時,它提供了響應的處理機制。

在微服務架構中,每個服務都有可能依賴其他服務,也有可能多個服務同時依賴一個服務,又或者存在服務之間的連環(huán)依賴(A 依賴 B,B 依賴 D)。

一旦被依賴的服務出現(xiàn)故障,Hystrix 可以通過預設的處理機制,調整服務的響應。例如:返回錯誤信息,用緩存或者兜底信息替代服務返回信息。

單個服務依賴多個服務,依賴服務中有一個出現(xiàn)問題,對整體產(chǎn)生影響。

多個服務依賴單個服務,單個服務出現(xiàn)故障,影響多個服務

應用 Hystrix 只需要兩步:

第一步,在“A”服務(消費者)上定義,調用“B”服務(生產(chǎn)者)出現(xiàn)故障時的處理方法。

調用“B”服務故障處理的方法,代碼片段

第二步,在“A”服務(消費者)調用“B”服務的方法的 Annotation 上面標注調用失敗需要執(zhí)行的“第一步”的這個方法。

聲明調用失敗方法,代碼片段

在“A”服務中加入 Hystrix

Zuul 如何訪問到微服務

上面把服務端的事情說的差不多了,如果“C”客戶端需要訪問“A”服務,系統(tǒng)通過什么方式告訴它哪個服務是“A”呢?

實際上這里缺少一個網(wǎng)關,把“C”客戶端與“A”服務鏈接起來的網(wǎng)關。

Zuul 就是這個網(wǎng)關,它的責任是過濾和路由。

Zuul 是鏈接客戶端和服務端的網(wǎng)關

還記得上面提到的 Eureka 服務注冊和服務發(fā)現(xiàn)嗎?Zuul 可以和 Eureka 一起合作,完成服務路由的工作。

首先,“A”服務在 Eureka 進行注冊,然后“C”客戶端向 Zuul 發(fā)起請求,訪問“A”服務。Zuul 向 Eureka 獲取“A”服務的地址,之后訪問“A”服務。

Zuul 與 Eureka 協(xié)同工作

Zuul 除了可以做路由,還可以做過濾器,針對權限驗證,金絲雀測試都可以用到它。這里簡單說說 Zuul 內部的運行機制。

Zuul 收到 HTTP 請求以后,會通知 Zuul Servlet 處理,與此同時會生成一個 Request Context 用來記錄請求的上下文信息,它會一直保持直到路由結束。

Zuul Filter Runner 接到 Zuul Servlet 的通知以后,會從 Request Context 中取請求的信息,并且交給 Filter Processer 處理,它會維護一套過濾和路由的規(guī)則,根據(jù)這些規(guī)則將請求發(fā)送到目標的服務。

Zuul 內部工作原理圖

Spring Cloud 微服務架構總結

說完了上面這些是不是對 Spring Cloud 理解更加深了。讓我們來回顧一下,Spring Cloud 是一個微服務架構,它為微服務開發(fā)提供了豐富的組件。

其中比較重要的五大組件分別是

  • Eureka:服務發(fā)現(xiàn),服務注冊。
  • Feign:服務調用請求。
  • Ribbon:服務之間負載均衡。
  • Hystrix:熔斷器。
  • Zuul:服務網(wǎng)關。

如果,用我們上面 ABC 的例子來記憶就是,A 調用 B(Eureka),A 發(fā)送請求(Feign),B 做橫向擴展以后,A 通過(Ribbon)找到 B,B 出現(xiàn)問題 A 通過熔斷機制(Hystrix)保證服務調用正常,C 通過 Zuul 找到 A。

用一張大圖來總結一下:

通過 ABC 理解 Spring Cloud 的五大組件

還可以把整個流程總結一下,客戶端請求ZuulEureka 獲取服務Feign 通信Ribbon 負載均衡Hystrix 熔斷:

用戶請求會最新發(fā)送給 Zuul,Zuul 是用來做 API 網(wǎng)關的。同時它也可以作為過濾器。

微服務的注冊操作需要通過 Eureka,作為服務發(fā)現(xiàn)和注冊中心,一方面記錄服務的注冊以及健康情況,一方面會協(xié)同 Zuul 做好服務訪問的工作。

微服務之間通訊,需要把數(shù)據(jù)打包發(fā)送,接受以后也需要解包讀取信息。這里可以使用 Feign 作為服務通訊的組件,配合 Ribbon 完成通信工作。

Robbin,其負責微服務集群的負載均衡工作。

服務出現(xiàn)故障,例如:業(yè)務異常,網(wǎng)絡異常等等。需要通過斷路器 Hystrix 來實現(xiàn)具體的處理操作,比如通知注冊中心服務異常,比如對服務進行降級處理。

這個時候服務注冊發(fā)現(xiàn)中心會標記服務異常,再有請求過來就不會發(fā)送到有異常的服務上去了。

同時服務發(fā)現(xiàn)注冊中心也會定期檢查服務的狀態(tài),一旦服務恢復狀態(tài)又把其放到訪問隊列中。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1 為什么需要服務發(fā)現(xiàn) 簡單來說,服務化的核心就是將傳統(tǒng)的一站式應用根據(jù)業(yè)務拆分成一個一個的服務,而微服務在這個基...
    謙小易閱讀 25,349評論 4 93
  • ?通過前面兩章對Spring Cloud Ribbon和Spring Cloud Hystrix的介紹,我們已經(jīng)掌...
    Chandler_玨瑜閱讀 214,581評論 15 140
  • 微服務架構模式的核心在于如何識別服務的邊界,設計出合理的微服務。但如果要將微服務架構運用到生產(chǎn)項目上,并且能夠發(fā)揮...
    java菜閱讀 3,057評論 0 6
  • 歷史類 1.《樞紐》 推薦理由:“這回我問的是外交學院世界政治研究中心主任施展老師。。。。 2017年,我遇到了一...
    馬輅閱讀 616評論 0 1
  • 記得第一次讀到“神農(nóng)嘗百草”的故事的時候,我感嘆從某種意義上講,神農(nóng)真是個很幸運的人。他嘗了一百種草竟然還能繼續(xù)工...
    現(xiàn)代魔法書閱讀 155評論 0 0

友情鏈接更多精彩內容