SpringCloud Alibaba系列(三) Sentinel流控


願你生命中有夠多的雲翳,造就一個美好的黃昏 

 

歡迎關注公眾號【渣男小四】,一個喜歡技術更喜歡藝術的青年



一.介紹

  流量控制(flow control),其原理是監控應用流量的 QPS 或並發線程數等指標,當達到指定的閾值時對流量進行控制,以避免被瞬時的流量高峰沖垮,從而保障應用的高可用性。

  

二.基於QPS/並發數的流量控制

  流量控制主要有兩種統計類型,一種是統計並發線程數,另外一種則是統計 QPS

   本教程基於SpringCloud Alibaba,所以先配置相關的文件

    1.pom.xml引入相關的坐標

       <!--Nacos坐標-->
     <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
     <!--sentinel坐標-->  <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!--sentinel持久化--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>

 

  2.yml配置

server: port: 8002 spring: application: name: dream-microservice-consumer cloud: sentinel: transport: dashboard: ip:8080  #sentinel服務地址,儀表盤端口默認為8080 port: 8719 #sentinel服務端口默認為8719,如果沖突了就+1,知道沒有端口沖突 nacos: discovery: server-addr: ip:8848 config: server-addr: ip:8848 file-extension: yaml

 

   流控模式

   直接模式

 

   1.建立一個簡單測試接口

 /** * 渣男小四 * @return
     */ @GetMapping("/flowLimit") public String flowLimit(){ return "FlowLimit Success"; }

 

  2.在儀表盤配置相應的流控規則如下圖:

    QPS為一秒最多只有一個請求


   

  3.測試接口

   如果正常的一秒鍾發起一次請求,則會返回正常的信息,如果一秒鍾發起多次請求,則會返回sentinel的限流提示。

    正常情況:


   

  請求過於頻繁的情況:


 

  並發線程數控制

   並發數控制用於保護業務線程池不被慢調用耗盡。例如,當應用所依賴的下游應用由於某種原因導致服務不穩定、響應延遲增加,對於調用者來說,意味着吞吐量下降和更多的線程數占用,極端情況下甚至導致線程池耗盡。為應對太多線程占用的情況,業內有使用隔離的方案,比如通過不同業務邏輯使用不同線程池來隔離業務自身之間的資源爭搶(線程池隔離)。這種隔離方案雖然隔離性比較好,但是代價就是線程數目太多,線程上下文切換的 overhead 比較大,特別是對低延時的調用有比較大的影響。Sentinel 並發控制不負責創建和管理線程池,而是簡單統計當前請求上下文的線程數目(正在執行的調用數目),如果超出閾值,新的請求會被立即拒絕,效果類似於信號量隔離。並發數控制通常在調用端進行配置。

  

  示例:代碼同上,只需要修改sentinel儀表盤,改為線程數,一秒只處理一個線程,如果線程過多,則不能進行處理,直接返回。

   每個請求需要處理1秒


 

 

   如上所示,在程序里面讓請求停了一秒鍾,然而一秒只能處理一個請求,當有大量的請求來的時候,sentinel就會返回限流提示。


 

  QPS和線程數的區別:就好比某個辦理處,人太多了,所以有一扇門擋住,QPS就是如果一秒只允許一個人進來,那么其他人連門都進不了,只有一個人能進門,線程數就是我允許所有的人都進門來,但是我現在只有一個worker,一秒鍾只能給一個人辦理業務,其他的人辦理不了,在程序里面就會報相應的錯。

 

  關聯模式

  流控模式為關聯的情況下,當關聯的資源達到預置時,就限流自己,就好比如果支付接口到達閾值,就限流下訂單的接口,這樣就能有效的防止多個資源和接口同時掛掉。

  例子:

   1.設置兩個接口flowLimit1和flowLimit2,當flowLimit2到達閾值時,flowLimit1接口就掛掉

 

  2.在sentinel儀表盤配置關聯,flowLimt1關於flowLimt2

 

  鏈路模式

  鏈路流控模式指的是,當從某個接口過來的資源達到限流條件時,開啟限流


 

  流控效果

  流量控制的效果包括直接拒絕(默認)、Warm Up、排隊等待

  

  快速失敗(默認)

   當到達限流條件,直接拋出異常(Blocked by Sentinel (flow limiting))

 

   Warm Up(預熱)

   當流量突然增大的時候,我們常常會希望系統從空閑狀態到繁忙狀態的切換的時間長一些。即如果系統在此之前長期處於空閑的狀態,我們希望處理請求的數量是緩步的增多,經過預期的時間以后,到達系統處理請求個數的最大值。Warm Up(冷啟動,預熱)模式就是為了實現這個目的的。

  這個場景主要用於啟動需要額外開銷的場景,例如建立數據庫連接等。

  它的實現是在 Guava 的算法的基礎上實現的。然而,和 Guava 的場景不同,Guava 的場景主要用於調節請求的間隔,即 Leaky Bucket,而 Sentinel 則主要用於控制每秒的 QPS,即我們滿足每秒通過的 QPS 即可,我們不需要關注每個請求的間隔,換言之,我們更像一個 Token Bucket。

  我們用桶里剩余的令牌來量化系統的使用率。假設系統每秒的處理能力為 b,系統每處理一個請求,就從桶中取走一個令牌;每秒這個令牌桶會自動掉落b個令牌。令牌桶越滿,則說明系統的利用率越低;當令牌桶里的令牌高於某個閾值之后,我們稱之為令牌桶"飽和"。

  當令牌桶飽和的時候,基於 Guava 的計算上,我們可以推出下面兩個公式:

  rate(c)=m*c+ coldrate

  其中,rate 為當前請求和上一個請求的間隔時間,而 rate 是和令牌桶中的高於閾值的令牌數量成線形關系的。cold rate 則為當桶滿的時候,請求和請求的最大間隔。通常是 coldFactor * rate(stable)

   通常冷啟動的過程系統允許通過的 QPS 曲線如下圖所示:


   

  默認 coldFactor 為 3(寫死的),即請求 QPS 從 threshold / 3 開始,經預熱時長逐漸升至設定的 QPS 閾值。


 

  如:默認的冷加載因子(coldFactor )是3,即請求 QPS 從 threshold / 3 開始(閾值為3),經過5秒的預熱時長,QPS從3恢復到10

  通俗易懂一點就是:前五秒鍾閾值為3,過了五秒鍾過后變為10


 

  排隊等待:

   Leaky Bucket 對應 流量整形 中的勻速器。它的中心思想是,以固定的間隔時間讓請求通過。當請求到來的時候,如果當前請求距離上個通過的請求通過的時間間隔不小於預設值,則讓當前請求通過;否則,計算當前請求的預期通過時間,如果該請求的預期通過時間小於規則預設的 timeout 時間,則該請求會等待直到預設時間到來通過(排隊等待處理);若預期的通過時間超出最大排隊時長,則直接拒接這個請求。

    這種方式適合用於請求以突刺狀來到,這個時候我們不希望一下子把所有的請求都通過,這樣可能會把系統壓垮;同時我們也期待系統以穩定的速度,逐步處理這些請求,以起到“削峰填谷”的效果,而不是拒絕所有請求。

  例如,我們去食堂里面打飯需要排隊,效果如下所示:

 

  Sentinel 勻速排隊等待策略是 Leaky Bucket 算法結合虛擬隊列等待機制實現的。

  勻速排隊模式暫時不支持 QPS > 1000 的場景。

 

  如下:設置為每秒允許有10次請求,則每個請求的平均時長為1000 / 10 = 100 ms,如果每秒超過了10個請求,則需要排隊等待,每個請求最長等待時間為10s

 

  至此,sentinel的限流就差不多了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM