天天看點

談談微服務中的限流、熔斷和降級

1.1 為什麼需要限流

對外的API服務

使用者增長過快

因為某個熱點事件(微網誌熱搜)

競争對象爬蟲

惡意的刷單

開學季(可預知)

這些情況都是無法預知的,不知道什麼時候會有10倍甚至20倍的流量打進來,如果真碰上這種情況,擴容是根本來不及的(彈性擴容都是虛談,一秒鐘能擴容完成嗎?)

對内的RPC服務

一個服務A的接口可能被BCDE多個服務進行調用,在B服務發生突發流量時,直接把A服務給調用挂了,導緻A服務對CDE也無法提供服務。

1、每個調用方采用線程池進行資源隔離

2、使用限流手段對每個調用方進行限流

1.2 常見的限流算法

常見的限流算法有:計數器、漏桶、令牌桶。

計數器算法

實作:采用計數器實作限流有點簡單粗暴,一般我們會限制一秒鐘的能夠通過的請求數,比如限流qps為100,算法的實作思路就是從第一個請求進來開始計時,在接下去的1s内,每來一個請求,就把計數加1,如果累加的數字達到了100,那麼後續的請求就會被全部拒絕。等到1s結束後,把計數恢複成0,重新開始計數。

弊端:如果我在機關時間1s内的前10ms,已經通過了100個請求,後面的990ms,隻能眼巴巴的把請求拒絕,這種現象稱為“突刺現象”,不平滑;

漏桶

為了消除"突刺現象",可以采用漏桶算法實作限流,漏桶算法這個名字就很形象,算法内部有一個容器,類似生活用到的漏鬥,當請求進來時,相當于水倒入漏鬥,然後從下端小口慢慢勻速的流出。不管上面流量多大,下面流出的速度始終保持不變。不管服務調用方多麼不穩定,通過漏桶算法進行限流,每10毫秒處理一次請求。因為處理的速度是固定的,請求進來的速度是未知的,可能突然進來很多請求,沒來得及處理的請求就先放在桶裡,既然是個桶,肯定是有容量上限,如果桶滿了,那麼新進來的請求就丢棄。

談談微服務中的限流、熔斷和降級

算法實作思路:可以準備一個隊列,用來儲存請求,另外通過一個線程池定期從隊列中擷取請求并執行,可以一次性擷取多個并發執行。

弊端:無法應對短時間的突發流量。

令牌桶

令牌桶算法是對漏桶算法的一種改進,桶算法能夠限制請求調用的速率,而令牌桶算法能夠在限制調用的平均速率的同時還允許一定程度的突發調用。在令牌桶算法中,存在一個桶,用來存放固定數量的令牌。算法中存在一種機制,以一定的速率往桶中放令牌。每次請求調用需要先擷取令牌,隻有拿到令牌,才有機會繼續執行,否則選擇選擇等待可用的令牌、或者直接拒絕。放令牌這個動作是持續不斷的進行,如果桶中令牌數達到上限,就丢棄令牌,是以就存在這種情況,桶中一直有大量的可用令牌,這時進來的請求就可以直接拿到令牌執行,比如設定qps為100,那麼限流器初始化完成一秒後,桶中就已經有100個令牌了,這時服務還沒完全啟動好,等啟動完成對外提供服務時,該限流器可以抵擋瞬時的100個請求。是以,隻有桶中沒有令牌時,請求才會進行等待,最後相當于以一定的速率執行。

談談微服務中的限流、熔斷和降級

算法實作思路:可以準備一個隊列,用來儲存令牌,另外通過一個線程池定期生成令牌放到隊列中,每來一個請求,就從隊列中擷取一個令牌,并繼續執行。

通過Google開源的guava包,使用它可以很輕松的建立一個令牌桶算法的限流器。

2.1 熔斷概念

在微服務架構中,微服務是完成一個單一的業務功能,這樣做的好處是可以做到解耦,每個微服務可以獨立演進。但是,一個應用可能會有多個微服務組成,微服務之間的資料互動通過遠端過程調用完成。這就帶來一個問題,假設微服務A調用微服務B和微服務C,微服務B和微服務C又調用其它的微服務。如果調用鍊路上某個微服務的調用響應時間過長或者不可用,對微服務A的調用就會占用越來越多的系統資源,進而引起系統崩潰,所謂的“雪崩效應”。

熔斷機制是應對雪崩效應的一種微服務鍊路保護機制。

服務熔斷的作用類似于我們家用的保險絲,當某服務出現不可用或響應逾時的情況時,為了防止整個系統出現雪崩,暫時停止對該服務的調用。

熔段解決如下幾個問題:

當所依賴的對象不穩定時,能夠起到快速失敗的目的;

快速失敗後,能夠根據一定的算法動态試探所依賴對象是否恢複

2.2 降級概念

服務降級是從整個系統的負荷情況出發和考慮的,對某些負荷會比較高的情況,為了預防某些功能(業務場景)出現負荷過載或者響應慢的情況

在其内部暫時舍棄對一些非核心的接口和資料的請求,而直接傳回一個提前準備好的fallback(退路)錯誤處理資訊。這樣,雖然提供的是一個有損的服務,但卻保證了整個系統的穩定性和可用性。

例如:當雙11活動時,把無關交易的服務統統降級,如檢視螞蟻深林,檢視曆史訂單,商品曆史評論,隻顯示最後100條等等。

2.3、降級、熔斷差別

相同點:

目的很一緻,都是從可用性可靠性着想,為防止系統的整體緩慢甚至崩潰,采用的技術手段;

最終表現類似,對于兩者來說,最終讓使用者體驗到的是某些功能暫時不可達或不可用;

粒度一般都是服務級别,當然,業界也有不少更細粒度的做法,比如做到資料持久層(允許查詢,不允許增删改);

自治性要求很高,熔斷模式一般都是服務基于政策的自動觸發,降級雖說可人工幹預,但在微服務架構下,完全靠人顯然不可能,開關預置、配置中心都是必要手段;

差別:

觸發原因不太一樣,服務熔斷一般是某個服務(下遊服務)故障引起,而服務降級一般是從整體負荷考慮;

管理目标的層次不太一樣,熔斷其實是一個架構級的處理,每個微服務都需要(無層級之分),而降級一般需要對業務有層級之分(比如降級一般是從最外圍服務開始)

實作方式不太一樣;服務降級具有代碼侵入性(由控制器完成/或自動降級),熔斷一般稱為自我熔斷。

Sentinel

Hystrix

Resilience4j

感謝你看到這裡,我是程式員麥冬,一個java開發從業者,深耕行業六年了,每天都會分享java相關技術文章或行業資訊