1. 程式人生 > >Spring Cloud Netflix微服務架構實踐

Spring Cloud Netflix微服務架構實踐

前言

系統一旦走向分散式,其複雜程度成倍增長,傳統單體應用只考慮業務邏輯的開發方式已經不再適用。正因其複雜性,目前只有業務需求大的大型網際網路公司才會(被迫)採用,而且需要投入大量的技術力量來開發基礎設施,也造成了小公司“用不起”分散式架構的情況。現在這一局面正在逐漸被打破,因為Netflix開源了其經過實戰考驗的一系列基礎設施構件,加上Spring Cloud的大力支援,開發分散式系統已經不再像以前那樣可怕了。

統一的配置管理

微服務意味著要將單體應用中的業務拆分成一個個子服務,每個服務的粒度相對較小,因此係統中會出現大量的服務。由於每個服務都需要必要的配置資訊才能執行,所以一套集中式的、動態的配置管理設施是必不可少的。Spring Cloud提供了Config Server來解決這個問題。Config Server的主要功能如下:

  • 集中化的配置檔案管理
    不再需要在每個服務部署的機器上編寫配置檔案,服務會向配置中心統一拉取配置自己的資訊。

  • 動態化的配置更新
    當配置發生變動時,服務不需要重啟即可感知到配置的變化並應用新的配置。

  • 將配置資訊以HTTP REST介面的形式暴露
    這使得非Java語言的服務也能享受到上面兩點功能。

Config Server的架構圖如下:
這裡寫圖片描述

工作流程如下:

  1. 配置中心感知到配置變化(如,git倉庫發生commit提交),向Bus投遞訊息
  2. Bus向服務廣播訊息
  3. 服務收到訊息後,主動向配置中心拉取新配置並應用

其中配置中心可叢集部署實現高可用。

服務的註冊發現和LB

Spring Cloud Netflix通過Eureka Server實現服務註冊中心,通過Ribbon實現軟負載均衡:
這裡寫圖片描述

Zone

Eureka支援Region和Zone的概念。其中一個Region可以包含多個Zone。Eureka在啟動時需要指定一個Zone名,即當前Eureka屬於哪個zone, 如果不指定則屬於defaultZone。Eureka Client也需要指定Zone, Client(當與Ribbon配置使用時)在向Server獲取註冊列表時會優先向自己Zone的Eureka發請求,如果自己Zone中的Eureka全掛了才會嘗試向其它Zone。當獲取到遠端服務列表後,Client也會優先向同一個Zone的服務發起遠端呼叫。Region和Zone可以對應於現實中的大區和機房,如在華北地區有10個機房,在華南地區有20個機房,那麼分別為Eureka指定合理的Region和Zone能有效避免跨機房呼叫,同時一個地區的Eureka壞掉不會導致整個該地區的服務都不可用。

Ribbon軟負載均衡

Ribbon在工作時分成兩步,第一步先選擇 Eureka Server, 它優先選擇在同一個Zone且負載較少的server, 第二步再根據使用者指定的策略,在從server取到的服務註冊列表中選擇一個地址。其中Ribbon提供了三種策略:輪詢、斷路器和根據響應時間加權。

宣告式HTTP REST客戶端Feign

Feign與Apache Http Client這類客戶端最大的不同,是它允許你通過定義介面的形式構造HTTP請求,不需要手動拼引數,使用起來與正常的本地呼叫沒有什麼區別:

@FeignClient(name = "ea")
public interface AdvertGroupRemoteService {

    @RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET)
    AdvertGroupVO findByGroupId(@PathVariable("groupId") Integer adGroupId);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

這裡我們只需要呼叫AdvertGroupRemoteService.findByGroupId()方法就能完成向目標主機發HTTP請求並封裝返回結果的效果。

斷路器、資源隔離與自我修復

斷路器(Cricuit Breaker)是一種能夠在遠端服務不可用時自動熔斷(開啟開關),並在遠端服務恢復時自動恢復(閉合開關)的設施,Spring Cloud通過Netflix的Hystrix元件提供斷路器、資源隔離與自我修復功能。下面介紹一下在分散式系統中為什麼需要斷路器。

在微服務架構中,對於客戶端的一個請求,我們可能需要呼叫多個子(微)服務,如圖所示:
圖片來自Hystrix官方文件

上圖中的請求需要呼叫A, P, H, I 四個服務,如果一切順利則沒有什麼問題,關鍵是如果I服務超時會出現什麼情況呢?
這裡寫圖片描述

當服務I由於某種原因無法響應時,使用者請求就會卡在服務 I 的遠端呼叫上,假如超時失敗時間設定為2秒,那麼在這2秒內容器的當前執行緒就會一直被堵塞在該呼叫中。 我們假設容器最大執行緒數為100, 如果此時又有另外99個請求都需要呼叫服務 I, 那麼這99個執行緒同樣會被堵塞,這樣就會因為容器執行緒耗盡而導致該應用無法響應其它任何請求因為一個服務掛掉而導致整個應用不可用顯然是無法接受的。那麼 Hystrix 是如何解決這個問題的呢?

資源隔離

首選,Hystrix對每一個依賴服務都配置了一個執行緒池,對依賴服務的呼叫會線上程池中執行。例如,我們設計服務 I 的執行緒池大小為20, 那麼 Hystrix會最多允許有20個容器執行緒呼叫服務 I, 如果超出20,Hystrix會拒絕並快速失敗。這樣即使服務 I 長時間未響應,容器最多也只能堵塞20個執行緒,剩餘80個執行緒仍然可以處理使用者請求。

快速失敗

快速失敗是防止資源耗盡的關鍵一點。當 Hystrix 發現在過去某段時間內對服務 I 的調用出錯率達到某個閥值時,Hystrix 就會“熔斷”該服務,後續任何向服務 I 的請求都會快速失敗,而不是白白讓呼叫執行緒去等待。

自我修復

處於熔斷狀態的服務,在經過一段時間後,Hystrix會讓其進入“半關閉”狀態,即允許少量請求通過,然後統計呼叫的成功率。如果這個請求都能成功,Hystrix 會恢復該服務,從而達到自我修復的效果。其中,在服務被熔斷到進入半關閉狀態之間的時間,就是留給開發人員排查錯誤並恢復故障的時間,開發人員可以通過監控措施得到提醒併線上排查。

監控方案

監控是保障分散式系統健康執行必不可少的方案。基於Spring Cloud,我們可以從兩個緯度進行監控:Hystrix斷路器的監控和每個服務監控狀況的監控。

下圖是 Hystrix 提供的 Dashboard 圖形化監控:
這裡寫圖片描述
可見圖中監控資訊應有盡有(呼叫成功率、平時響應時間、呼叫頻次、斷路器狀態等)。我們可以通過程式設計的方式定時獲取該資訊,並在斷路器熔斷時通過簡訊、郵件等方式通知開發者。

Hystrix的監控資料預設是儲存在每個例項的記憶體中的,Spring Boot提供了多種方式,可以匯入到Redis、TSDB以供日後分析使用。

除此之外,Spring Cloud還提供了對單個例項的監控:
這裡寫圖片描述
這裡寫圖片描述

其中包含了介面呼叫頻次,響應時間,JVM狀態,動態日誌等各種開發者關心的資訊。

總結

以上是Spring Cloud Netflix為微服務架構提供的支援,Spring Cloud專案還有許多其它子專案有著更強大的功能,通過這些元件,我們能以 Spring Boot 簡潔的風格快速搭建微服務架構,並讓開發人員專注於業務,讓分散式對開發者儘量透明。

  原文地址:http://blog.csdn.net/neosmith/article/details/52204113