1. 程式人生 > >微服務 - 如何進行服務限流和熔斷

微服務 - 如何進行服務限流和熔斷

### 一、服務雪崩 ​微服務架構是將單個應用程式被劃分成各種小而連線的服務,每一個服務完成一個單一的業務功能。相對於傳統的單體服務,微服務具有隔離性、技術異構性、可擴充套件性以及簡化部署等優點。通常一個應用由多個微服務組成,微服務之間的資料互動需要通過遠過程呼叫的方式完成。 ​下圖是一個微服務之間互相呼叫的場景: ![](https://img2020.cnblogs.com/blog/48183/202011/48183-20201107103940025-584564851.png) ​微服務A呼叫微服務B、C和D,微服務C又呼叫微服務E。假設某一時刻,微服務E變為不可用。微服務C需要等待微服務E返回結果,於是請求就會逐漸堆積在微服務C,形成阻塞。隨著微服務C堆積的請求不斷增加,微服務A也會隨之慢慢阻塞。因為伺服器所能支撐的併發數有限,所以最終會耗盡伺服器資源,從而導致呼叫鏈條上更多的微服務不可用,形成雪崩效應。這種由一個服務崩潰導致整條服務鏈崩潰的情況,我們就稱之為服務雪崩。 ​ 在微服務架構中,通常有兩種情況會導致服務雪崩: 1. 突發性的訪問量劇增,超出了服務處理極限 2. 呼叫鏈條上某個服務出現故障或者響應慢(延遲) 針對以上這兩種情況,產生了對應的解決方案:服務限流和服務熔斷。 ### 二、 服務限流 ​ 服務限流是指在一定時間段內限制服務的請求量以保護系統,主要用於防止突發流量而導致的服務崩潰,比如秒殺、搶購、雙十一等場景,也可以用於安全目的,比如應對外部暴力攻擊。 ​ 常用的限流演算法有以下幾種: - **計數器演算法** ​ 通過維護一個內部計數器,對一段時間的服務請求進行累計,判斷計數器是否達到預先設定的閾值。如果沒有達到閾值,就允許請求通過,並且計數器加1;如果達到閾值,則拒絕服務,拋棄請求。進入下一個計時週期後,計數器清零,重新計數。 ​ 計數器演算法是限流演算法中最簡單的演算法,缺點是有突刺現象,不僅請求通過的速率不均勻,而且請求輸出的速率也不均勻,對後續處理的併發要求比較高。比如:設定服務週期為1秒,請求的上限閾值為1000。如果前1ms內已經收到1000個請求,那麼剩下的時間都只能拒絕,而且後端服務需要併發處理1000個請求。 - **漏桶演算法** ​ 漏桶演算法的原理可以這樣理解,將服務請求想象成流入漏桶的水,漏桶中的水以恆定的速率從桶底流出,當流入漏桶的水速度過快,超過了漏桶容量時,則直接溢位。所以,漏桶演算法能夠控制服務請求按照固定速率均勻輸出,平滑突發流量,實現流量整形,為後續處理提供一個穩定的流量。但是,漏桶演算法無法控制請求按照一定的速率均勻輸入。 - **令牌桶演算法** ​ 令牌桶演算法是速率限制(Rate Limiting)和流量整形(Traffic Shaping)中最常使用的一種演算法。典型情況下,令牌桶演算法用來控制傳送到網路上的資料的數目,並允許突發資料的傳送。 ​ 首先設定一個可以存放固定數量的令牌桶,使用某種機制以恆定的速度產生令牌。每次請求呼叫時,都必須去桶中獲取令牌,只有拿到令牌,才能放行,否則只能等待可用的令牌,或者直接拒絕。如果桶中的令牌消耗的速度小於產生的速度,令牌就會不斷地增多,直至填滿,再產生的令牌就會從桶中溢位。 ​ 所以,令牌桶演算法既可以控制請求均勻輸入的速度,又可以控制請求的均勻輸出速率。 #### 三、服務熔斷 ​ 我們在各種場景下都會接觸到熔斷這兩個字。高壓電路中,如果某處電壓過高,熔斷器就會熔斷,對電路進行保護。股票交易中,如果股票漲跌幅過大,也會採用熔斷機制,暫停交易,來控制交易風險。 ​ 同樣,在微服務架構中,熔斷機制也是起著類似的作用。當呼叫鏈路中的某個微服務長時間不可用或者有延遲,響應過慢,系統就會熔斷對該節點微服務的呼叫,快速返回錯誤資訊。當監控到該微服務正常工作後,再次恢復該呼叫鏈路。 #### 四、Hystrix ​ 服務熔斷和服務限流作為微服務架構中作為服務治理的重要手段,在很多開源框架或者產品中都包含了此類功能。比如阿里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 非常簡單: ``` package main import ( "github.com/afex/hystrix-go/hystrix" "log" ) func main() { // 每一類微服務、遠端系統、第三方庫的呼叫都被包裝為一個命令, // 呼叫之前需要先行設定相關的配置資訊 hystrix.ConfigureCommand( "ServiceA", // 命令名稱 hystrix.CommandConfig{ Timeout: 1000, // 超時時間設定(毫秒) MaxConcurrentRequests: 1, // 最大併發請求數 ErrorPercentThreshold: 50, // 錯誤率閾值,超過閾值將熔斷服務 SleepWindow: 5000, // 服務熔斷後,過多長時間,熔斷器再次檢測是否開啟(毫秒) RequestVolumeThreshold: 20, // 服務熔斷前,所需的最小請求量,請求閾值 熔斷器是否開啟首先要滿足這個條件;這裡的設定表示至少有5個請求才進行ErrorPercentThreshold錯誤百分比計算 }) // 使用hystrix呼叫遠端服務,並根據命令名稱啟用ConfigureCommand中設定的引數 _ = hystrix.Do( "ServiceA", // 命令名稱 // 執行函式 func() error { // 呼叫遠端服務 log.Println("invoke a remote service") return nil }, // 失敗回退函式 func(err error) error { log.Println("fall back") return err }, ) } ``` 注: 本文全部原始碼位於:https://github.com/wangshizebin/micro-service 本文時候用的開發工具為:[goland](http://www.sousou88.com/software/2072802.html) 來自 [嗖嗖下載](http://www.sousou88.com)