微服務架構是将單個應用程式被劃分成各種小而連接配接的服務,每一個服務完成一個單一的業務功能。相對于傳統的單體服務,微服務具有隔離性、技術異構性、可擴充性以及簡化部署等優點。通常一個應用由多個微服務組成,微服務之間的資料互動需要通過遠過程調用的方式完成。
下圖是一個微服務之間互相調用的場景:

微服務A調用微服務B、C和D,微服務C又調用微服務E。假設某一時刻,微服務E變為不可用。微服務C需要等待微服務E傳回結果,于是請求就會逐漸堆積在微服務C,形成阻塞。随着微服務C堆積的請求不斷增加,微服務A也會随之慢慢阻塞。因為伺服器所能支撐的并發數有限,是以最終會耗盡伺服器資源,進而導緻調用鍊條上更多的微服務不可用,形成雪崩效應。這種由一個服務崩潰導緻整條服務鍊崩潰的情況,我們就稱之為服務雪崩。
在微服務架構中,通常有兩種情況會導緻服務雪崩:
突發性的通路量劇增,超出了服務處理極限
調用鍊條上某個服務出現故障或者響應慢(延遲)
針對以上這兩種情況,産生了對應的解決方案:服務限流和服務熔斷。
服務限流是指在一定時間段内限制服務的請求量以保護系統,主要用于防止突發流量而導緻的服務崩潰,比如秒殺、搶購、雙十一等場景,也可以用于安全目的,比如應對外部暴力攻擊。
常用的限流算法有以下幾種:
計數器算法
通過維護一個内部計數器,對一段時間的服務請求進行累計,判斷計數器是否達到預先設定的門檻值。如果沒有達到門檻值,就允許請求通過,并且計數器加1;如果達到門檻值,則拒絕服務,抛棄請求。進入下一個計時周期後,計數器清零,重新計數。
計數器算法是限流算法中最簡單的算法,缺點是有突刺現象,不僅請求通過的速率不均勻,而且請求輸出的速率也不均勻,對後續處理的并發要求比較高。比如:設定服務周期為1秒,請求的上限門檻值為1000。如果前1ms内已經收到1000個請求,那麼剩下的時間都隻能拒絕,而且後端服務需要并發處理1000個請求。
漏桶算法
漏桶算法的原理可以這樣了解,将服務請求想象成流入漏桶的水,漏桶中的水以恒定的速率從桶底流出,當流入漏桶的水速度過快,超過了漏桶容量時,則直接溢出。是以,漏桶算法能夠控制服務請求按照固定速率均勻輸出,平滑突發流量,實作流量整形,為後續處理提供一個穩定的流量。但是,漏桶算法無法控制請求按照一定的速率均勻輸入。
令牌桶算法
令牌桶算法是速率限制(Rate Limiting)和流量整形(Traffic Shaping)中最常使用的一種算法。典型情況下,令牌桶算法用來控制發送到網絡上的資料的數目,并允許突發資料的發送。
首先設定一個可以存放固定數量的令牌桶,使用某種機制以恒定的速度産生令牌。每次請求調用時,都必須去桶中擷取令牌,隻有拿到令牌,才能放行,否則隻能等待可用的令牌,或者直接拒絕。如果桶中的令牌消耗的速度小于産生的速度,令牌就會不斷地增多,直至填滿,再産生的令牌就會從桶中溢出。
是以,令牌桶算法既可以控制請求均勻輸入的速度,又可以控制請求的均勻輸出速率。
我們在各種場景下都會接觸到熔斷這兩個字。高壓電路中,如果某處電壓過高,熔斷器就會熔斷,對電路進行保護。股票交易中,如果股票漲跌幅過大,也會采用熔斷機制,暫停交易,來控制交易風險。
同樣,在微服務架構中,熔斷機制也是起着類似的作用。當調用鍊路中的某個微服務長時間不可用或者有延遲,響應過慢,系統就會熔斷對該節點微服務的調用,快速傳回錯誤資訊。當監控到該微服務正常工作後,再次恢複該調用鍊路。
服務熔斷和服務限流作為微服務架構中作為服務治理的重要手段,在很多開源架構或者産品中都包含了此類功能。比如阿裡dubbo,Netflix Hystrix,go-micro,go-kit等。
Hystrix是Netflix公司的開源項目,它是一個延遲和故障容錯庫,旨在隔離對遠端系統、服務和第三方庫的通路點,防止級聯故障,并在無法避免發生故障的複雜分布式系統中實作了彈性。
Hystrix項目使用了java語言開發,代碼托管位址為:https://github.com/Netflix/Hystrix。另外,有人使用go語言将該項目進行了移植,代碼托管位址為:https://github.com/afex/hystrix-go/hystrix。
Hystrix可以做到以下事情:
通過控制延遲和故障來保障第三方服務調用的可靠性
在複雜的分布式系統中防止級聯故障,防止雪崩
快速失敗、快速恢複
回退并優雅降級
提供近實時監控、報警和操作控制
Hystrix 能使你的系統在出現依賴服務失效的時候,通過隔離系統所依賴的服務,防止服務級聯失敗,同時提供失敗回退機制,更優雅地應對失效,并使你的系統能更快地從異常中恢複。
使用Hystrix 非常簡單: