The microservice architectural style is an approach to developing a
single application as a suite of small services, each running in its
own process and communicating with lightweight mechanisms, often an
HTTP resource API.htmlThese services are built around business capabilities and
independently deployable by fully automated deployment machinery.編程There is a bare minimum of centralized management of these services ,
which may be written in different programming languages and use
different data storage technologies.segmentfault
以上是來自James Lewis 和 Martin Fowler關於微服務架構的定義。概括起來,有如下幾點:緩存
在整個微服務架構中,主角天然是一個個獨立部署,獨立運行的服務,而若是缺乏一種管理這些服務的機制,就像這個社會忽然沒有了道德法律的約束了,整個微服務架構也就不成體系了。安全
筆者所理解的微服務架構大體是這個樣子的:服務器
從這張圖上能夠看出,除了核心的微服務以外,還加入了API網關(Gateway)和註冊發現中心(Registry)。可是這張圖還並非很完美,只能算是把一些核心機制表現出來了。網絡
筆者還沒想到用什麼樣的姿式能把微服務的各個機制較爲完整的表如今一張圖上,仍是費一些筆墨加以敘述吧!架構
咱們能夠將Gateway視爲整個系統的Entry Point,是具備很是重要的戰略意義的,從上圖中的位置可見一斑。讓咱們先考慮一個問題:app
問:爲何須要Gateway?這部分能夠捨棄嗎?運維
答:從服務的用戶角度考慮,沒有Gateway,就意味着須要瞭解每一個服務對外暴露的接口,這無疑是一個繁雜而毫無心義的工做;從服務的管理者角度考慮,沒有Gateway,不管是平常的開發工做,仍是往後的維護擴展工做,都將是一個嚴峻的考驗。
因此結論很顯然,Gateway對於整個微服務架構體系來講是不可或缺的。
實際上,咱們的部署策略一般是一個服務部署多個實例,那麼客戶端發送一個請求過來,Gateway應該路由到哪一個實例上呢?
是時候讓Load Balance出場了。
因此,若是是以上的部署策略的話,一般是須要在Gateway和Services之間加一層Load Balance,經過必定的轉發策略,最終路由到其中的一個服務實例上。
咱們不妨再大膽假設一下:若是有多個Gateway,那會怎麼樣?
一般有這種考慮,是由於背後的服務數量很是多了,一個Gateway承載不了這麼大的流量,因此才考慮多加幾個幫手,每一個Gateway路由一部分服務,最後能夠造成一個Gateway的集羣。
這個時候,整個架構的複雜度又上升了一個層次,新的問題又產生了,對於這羣Gateway,必需要有效的管理起來。
簡單的解決辦法就是在這羣Gateway前面加一個Load Balance,大概是這個樣子:
可是前面有多個Load Balance又該怎麼辦呢?
……
這個問題還沒完沒了了。只能是依實際狀況而定了,這讓我想起了一句話:
在Gateway層面還有不少好玩的東西,好比作監控,限流什麼的。Gateway的實現手段也是多樣的,NodeJs,Zuul,Nginx等等。
文章開頭便提到了,微服務之間一般以REST API形式進行通信。這裏對REST稍做解釋。
REST API並非那麼神祕,REST是創建在HTTP請求之上的,因此REST請求本質上是HTTP請求。
REST是面向資源(resources)的架構,API的每種操做均可以認爲是資源的狀態轉移。
有三個重要的概念:
當你的技術團隊決定使用REST架構時,有兩個細節須要斟酌一下:
既然是基於HTTP協議,咱們不得不考慮由於各類緣由致使一次請求失敗了的問題。
一般狀況下,咱們會在系統中引入重試機制。請求重試的策略也不盡相同,好比最大重試3次,5秒內重試3次,若是多實例,還能夠設置在每一個實例上容許的最大重試次數。那麼,即使是把重試次數都用光了,請求仍是沒法到達,該怎麼應對呢?
咱們試着感覺一下:
Service-1由於某種緣由被迫下線了,若是沒有其餘副本集的支撐,那麼路由到Service-1的全部鏈路都將會被迫中斷。若是這種情況不能儘快改善的話,可能在數秒內致使全部應用資源(線程,隊列等)被耗盡,整條請求鏈路將會被拖累,甚至致使整個系統癱瘓。
這就是經典的雪崩效應(Cascading Failure)。
此時,須要在通向各個服務的鏈路上安插一個開關,就像家裏面的空氣開關,一旦遇到緊急狀況,就會自動斷開鏈路,不至於影響到其餘的鏈路,進而保證整個系統的正常運行。
這就是所謂的熔斷機制(Circuit Breaker)。這個機制並非IT界獨有的,在金融界也是赫赫有名的。這些概念都是來源於生活,提煉出一個又一我的類生存的法則。
還有一個與熔斷相近的概念:降級。
在微服務領域,「服務熔斷」和「服務降級」確實會對初學者形成必定的困惑。
其實仔細推敲一下,也不難理解。
二者都是出於對系統穩定性和安全性考慮,而且達到了必定的條件纔會觸發。不一樣的是觸發的方式和場景是不同的。
服務熔斷通常是系統根據預設的條件自動觸發的,好比連續請求失敗10次,爲了不形成進一步的損失,系統直接讓對應的服務下線。此時,開關至關於出於Closed狀態,等到服務從新上線,創建了心跳鏈接後,開關狀態就轉換成Open狀態。
服務降級的觸發能夠是人工干預的,也能夠是系統自動觸發的。這時候,服務之間是有層次之分的,被降級的某些服務的可用性下降了,用戶在使用的時候,有時候會得不到預期的結果。
這二者之間也有必定的關係,總結起來就是:
因爲長期的服務降級,致使了永久的服務熔斷。
若是還不是很清楚,能夠看我附上的第4個參考文獻。
在高度自治的微服務架構中,註冊與發現中心(Registry)這個角色是十分重要的。
Registry的做用就比如是一本書的目錄,經過目錄能夠找到相應的內容。Registry裝載的就是微服務的元數據。當一個服務嘗試去調用另外一個服務,就會去Registry上請求一份元數據,找到被調用的服務在什麼地方。
這樣看來,每一個服務均可以看做是一個Registry Client,Gateway也不例外。
Registry如此重要,一般我會但願其高可用,因此至少會爲其多部署一個副本,每一個Registry都持有一份完整的服務元數據。
此處不得再次說起文章開頭說到的去中心化的服務管理機制。
在SOA架構體系中,ESB是整個系統的中心,若是ESB癱瘓了,那麼也就意味着整個系統就不可用了。
微服務與SOA的一個重大區別就是去ESB,也就是去中心化。也就意味着,當Registry所有下線了,各個服務仍能正常運行。其中,作的一個主要的工做就是,每一個Registry Client都緩存一份服務的元數據信息,以備不時之需。
在分佈式系統領域有個著名的CAP定理:
這三個特性在任何分佈式系統中不能同時知足,最多同時知足兩個。架構師不要將精力浪費在如何設計能知足三者的完美分佈式系統,而是應該進行取捨。
在SOA架構體系中,ESB優先知足的是一致性,以zookeeper爲例,在使用Zookeeper獲取服務列表時,若是zookeeper正在選主,或者zookeeper集羣中半數以上機器不可用,那麼將就沒法得到數據了,因此說,zookeeper不能保證服務可用性,知足的是CP兩個條件。
可是就服務發現這個場景來講,若是數據達不到一致性的要求,並不會形成什麼災難性後果,咱們應該更看重的是服務的可用性,從這個方面考慮,AP是賽過CP的。這也是Spring Cloud Netflix在設計Eureka時遵照AP原則的緣由。
這是本文的最後一部份內容,也算是微服務領域的一個「高級話題」。
在筆者看來,調用鏈的跟蹤算是一種運維手段,要作好這一部分的工做,並非那麼簡單。
以往在單體應用環境下,全部的業務都在同一個服務器上,若是服務器出現錯誤和異常,咱們只要盯住一個點,就能夠快速定位和處理問題。
而微服務的架構已經決定了系統是在分佈式環境下完成一系列的業務活動的,此時,對於問題的追蹤和定位會變得比較麻煩。
鏈路跟蹤工具常見於一些中大型的系統,由於人肉排查問題的效率實在是過低了。
即使不是排查問題,若PM想跟蹤一下業務流,也會逐漸變得不可能了。
這是一張讓人看了會產生不適感的圖片:
這張圖片描述的是各個服務節點的調用關係,很恐怖,對不對?
對於鏈路跟蹤工具的實現,著名的有Twitter Zipkin,Google Dapper。至於工具的介紹,不在本文的討論範疇內,筆者將會另起新篇。
本文介紹了微服務架構風格的定義以及4個與微服務治理相關的技術概念,其實也是對於當下DevOps理念的一種體現。
但願對你有所幫助。
THANKS!
參考文獻:
六、我所瞭解的微服務
每日干貨分享,傳遞互聯網世界有價值的訊息,盡在「技術匯」。