Spring Cloud(Finchley版)-12-微服務容錯三板斧

http://www.globalshopping.top

至此,我們已實現服務發現、負載均衡,同時,使用Feign也實現了良好的遠程調用——我們的代碼是可讀、可維護的。理論上,我們現在已經能構建一個不錯的分佈式應用了,但微服務之間是通過網絡通信的,網絡可能出問題;微服務本身也不可能100%可用。

如何提升應用的可用性呢?這是我們必須考慮的問題——

舉個例子:某大型系統中,服務A調用服務B,某個時刻,微服務B突然崩潰了。微服務A中,依然有大量請求在請求B,如果沒有任何措施,微服務A很可能很快就會被拖死——因爲在Java中,一次請求往往對應着一個線程,如果不做任何措施,那意味着微服務A請求B的線程要等Feign Client/RestTemplate超時纔會釋放(這個時間一般非常長,長達幾十秒),於是就會有大量的線程被阻塞,而線程又對應着計算資源(CPU/內存),於是乎,大量的資源被浪費,並且越積越多,最終服務器終於沒有資源給微服務A浪費了,微服務A也掛了。

因此,在大型應用中,微服務之間的容錯必不可少,下面來討論如何實現微服務的容錯。

應用容錯三板斧

超時機制

超時機制你懂的,配置一下超時時間,例如1秒——每次請求在1秒內必須返回,否則到點就把線程掐死,釋放資源!

思路:一旦超時,就釋放資源。由於釋放資源速度較快,應用就不會那麼容易被拖死。

艙壁模式

有興趣的可以先了解一下船艙構造——一般來說,現代的輪船都會分很多艙室,艙室之間用鋼板焊死,彼此隔離。這樣即使有某個/某些船艙進水,也不會影響其他艙室,浮力夠,船不會沉。

軟件世界裏的倉壁模式可以這樣理解:M類使用線程池1,N類使用線程池2,彼此的線程池不同,並且爲每個類分配的線程池較小,例如coreSize=10。舉個例子:M類調用B服務,N類調用C服務,如果M類和N類使用相同的線程池,那麼如果B服務掛了,M類調用B服務的接口併發又很高,你又沒有任何保護措施,你的服務就很可能被M類拖死。而如果M類有自己的線程池,N類也有自己的線程池,如果B服務掛了,M類頂多是將自己的線程池佔滿,不會影響N類的線程池——於是N類依然能正常工作,

思路:不把雞蛋放在一個籃子裏。你有你的線程池,我有我的線程池,你的線程池滿了和我沒關係,你掛了也和我沒關係。

斷路器

現實世界的斷路器大家肯定都很瞭解,每個人家裏都會有斷路器。斷路器實時監控電路的情況,如果發現電路電流異常,就會跳閘,從而防止電路被燒燬。

軟件世界的斷路器可以這樣理解:實時監測應用,如果發現在一定時間內失敗次數/失敗率達到一定閾值,就“跳閘”,斷路器打開——此時,請求直接返回,而不去調用原本調用的邏輯。

跳閘一段時間後(例如15秒),斷路器會進入半開狀態,這是一個瞬間態,此時允許一次請求調用該調的邏輯,如果成功,則斷路器關閉,應用正常調用;如果調用依然不成功,斷路器繼續回到打開狀態,過段時間再進入半開狀態嘗試——通過”跳閘“,應用可以保護自己,而且避免浪費資源;而通過半開的設計,可實現應用的“自我修復“。

TIPS:

斷路器的提出人也是Martin Fowler,”微服務“這個名詞被廣泛瞭解,也和他有密不可分的關係。Martin Fowler的博客:http://www.martinfowler.com 。

斷路器狀態轉換可如下圖所示:

斷路器狀態轉換示意圖

本文較短,但相信已經用通俗的語言講解了常見的幾種容錯機制——目前Spring Cloud生態中,支持的斷路器有:Hystrix、Resilience4J、Alibaba Sentinel,雖然彼此實現有較大差異,但本質原理是相通的。

本節是斷路器的基石,在理解原理後,你會發現用不同的實現只是使用的依賴和註解不大一樣而已。

下一節,將着重講解如何使用Hystrix實現微服務的容錯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章