本章介紹Sentinel流量控制,與對Sentinel的基本概念,請參考【SpringCloud】Spring Cloud Alibaba 之 Sentinel哨兵介紹入門(二十九)
Sentinel流量控制介紹
流量控制(flow control),其原理是監控應用流量的 QPS 或並發線程數等指標,當達到指定的閾值時對流量進行控制,以避免被瞬時的流量高峰沖垮,從而保障應用的高可用性。
FlowSlot
會根據預設的規則,結合前面 NodeSelectorSlot
、ClusterNodeBuilderSlot
、StatisticSlot
統計出來的實時信息進行流量控制。
限流的直接表現是在執行 Entry nodeA = SphU.entry(resourceName)
的時候拋出 FlowException
異常。FlowException
是 BlockException
的子類,您可以捕捉 BlockException
來自定義被限流之后的處理邏輯。
同一個資源可以創建多條限流規則。FlowSlot
會對該資源的所有限流規則依次遍歷,直到有規則觸發限流或者所有規則遍歷完畢。
一條限流規則主要由下面幾個因素組成,我們可以組合這些元素來實現不同的限流效果:
resource
:資源名,即限流規則的作用對象count
: 限流閾值grade
: 限流閾值類型(QPS 或並發線程數)limitApp
: 流控針對的調用來源,若為default
則不區分調用來源strategy
: 調用關系限流策略controlBehavior
: 流量控制效果(直接拒絕、Warm Up、勻速排隊)
以下是關於流量控制中名詞解析
資源名:唯一名稱、默認請求路徑 針對來源:Sentinel可以針對調用者進行限流,填寫微服務名,默認default(不區分來源) 閥值類型/單機閥值: QPS(每秒鍾的請求數量):當調用該api的QPS達到閥值的時候,進行限流 線程數:當調用該api的線程數達到閥值的時候,進行限流 是否集群:不需要集群 流控模式: 直接:api達到限流條件時,直接限流 關聯:當關聯的資源達到閥值時,就限流自己 鏈路:只記錄指定鏈路上的流量(指定資源從入口資源進來的流量,如果達到閥值,就限流)【api級別的針對來源】 流控效果: 快速失敗:直接失敗,拋異常 Warm Up:根據codeFactor(冷加載因子,默認3)的值,從閥值/codeFactor,經過預熱時長,才達到設置的QPS閥值 排隊等待:勻速排隊,讓請求以均勻的速度通過,閥值類型必須設置為QPS,否則無效
Sentinel流量控制Demo
本章使用項目搭建參考:【SpringCloud】Spring Cloud Alibaba 之 Sentinel哨兵介紹入門(二十九)代碼
基於QPS的流量控制
當 QPS 超過某個閾值的時候,則采取措施進行流量控制。流量控制的效果包括以下幾種:直接拒絕、Warm Up、勻速排隊。對應 FlowRule
中的 controlBehavior
字段。
1、搭建項目,Controller內容如下:
1 @RestController 2 public class FlowLimitController { 3 4 @GetMapping("/testA") 5 public String testA(){ 6 return "--------testA"; 7 } 8 9 @GetMapping("/testB") 10 public String testB(){ 11 return "--------testB"; 12 } 13 }
2、將項目啟動,以及Sentinel啟動,添加流控規則,如下:
3、設置流控規則,每秒鍾的請求數量為1,流控效果為快速失敗,如下,保存后,即生效
4、測試
1)瀏覽器訪問地址:http://localhost:8401/testA,正常訪問
2)快速點擊瀏覽器刷新按鈕,刷新界面,頁面顯示:Blocked by Sentinel (flow limiting)
基於並發數的流量控制
1、繼續使用以上項目,修改testA方法,如下:
1 @GetMapping("/testA") 2 public String testA(){ 3 try { 4 Thread.sleep(800); 5 } catch (InterruptedException e) { 6 e.printStackTrace(); 7 } 8 return "--------testA"; 9 }
2、編輯流量規則,將流控規則改為當調用該api的線程數達到1的時候,進行限流,如下:
3、測試
1)重新啟動項目
2)使用瀏覽器單次請求,http://localhost:8401/testA,正常顯示
2)使用JMeter進行並發測試請求:http://localhost:8401/testA,響應內容為:Blocked by Sentinel (flow limiting)
流控模式:直接
上面2個例子,流控模式都是直接,對自己本身資源的限制。
流控模式:關聯
當兩個資源之間具有資源爭搶或者依賴關系的時候,這兩個資源便具有了關聯。像對數據庫同一個字段的讀操作和寫操作存在爭搶,讀的速度過高會影響寫得速度,寫的速度過高會影響讀的速度。如果放任讀寫操作爭搶資源,則爭搶本身帶來的開銷會降低整體的吞吐量。
示例
1、項目代碼還是以上的項目代碼
2、編輯流量規則,設置資源testA關聯的testB,當testB達到閥值時,testA被限流。如下:
3、測試
1)啟動項目
2)使用瀏覽器請求,http://localhost:8401/testA,正常顯示
3)使用JMeter不停的循環請求:http://localhost:8401/testB,testB請求結果都正確
4)然后使用瀏覽器請求,http://localhost:8401/testA,無法正常顯示,資源限制
流控模式:鏈路
1、項目代碼還是以上的項目代碼,Controllerh中testB方法
1 @GetMapping("/testB") 2 public String testB(){ 3 return "--------testB"; 4 }
2、查看簇點鏈路,發現/test,資源入口是sentinel_web_servlet_context
3、刪除其他流控規則,新增流量規則,設置資源testB鏈路限流,如下:、
4、測試
1)啟動項目
2)使用瀏覽器請求,http://localhost:8401/testB,正常顯示
3)快速點擊瀏覽器刷新按鈕,刷新界面,頁面顯示:Blocked by Sentinel (flow limiting)
流控效果:快速失敗
以上例子顯示了快速失敗的效果,快速失敗(RuleConstant.CONTROL_BEHAVIOR_DEFAULT
)方式是默認的流量控制方式,當QPS超過任意規則的閾值后,新的請求就會被立即拒絕,拒絕方式為拋出FlowException
。這種方式適用於對系統處理能力確切已知的情況下,比如通過壓測確定了系統的准確水位時。
流控效果:Warm Up(預熱)
Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP
)方式,即預熱/冷啟動方式。當系統長期處於低水位的情況下,當流量突然增加時,直接把系統拉升到高水位可能瞬間把系統壓垮。通過"冷啟動",讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮。
應用場景:
如:秒殺系統在開啟瞬間,會有很多流量上來,很有可能把系統打死,預熱方式就是把為了保護系統,可慢慢的把流量放進來,慢慢的把閥值增長到設置的閥值
案例:
閥值為10 + 預熱時長設置5秒
系統初始化的閥值為10/3 約等於 3,即閥值剛開始為3;然后過了5秒閥值才慢慢升高恢復到10
1、項目代碼還是以上的項目代碼,Controllerh中testC方法
1 @GetMapping("/testC") 2 public String testC(){ 3 return "--------testC"; 4 }
2、新增流量規則,設置資源testC,單機閥值為10,流控效果為Warm Up,預熱時長為5秒,如下:
3、測試
1)啟動項目
2)使用瀏覽器訪問地址,http://localhost:8401/testC,正常顯示
3)以每秒5次的刷新,一直刷新界面,效果,可以看到部分請求返回錯誤
4)5秒鍾過后,還是以以每秒5次的刷新速度,刷新界面,請求正常
流控效果:排隊等待
排隊等待(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER
)方式會嚴格控制請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應的是漏桶算法。
這種方式主要用於處理間隔性突發的流量,例如消息隊列。想象一下這樣的場景,在某一秒有大量的請求到來,而接下來的幾秒則處於空閑狀態,我們希望系統能夠在接下來的空閑期間逐漸處理這些請求,而不是在第一秒直接拒絕多余的請求。
案例
1、項目代碼還是以上的項目代碼,Controllerh中testA方法
1 @GetMapping("/testA") 2 public String testA(){ 3 try { 4 Thread.sleep(800); 5 } catch (InterruptedException e) { 6 e.printStackTrace(); 7 } 8 return "--------testA"; 9 }
2、新增流量規則,設置資源testA,流控效果為排隊等待,超時時間為20000毫秒,如下:
3、測試
1)啟動項目
2)使用瀏覽器訪問地址,http://localhost:8401/testA,正常顯示
3)使用JMeter並發10個請求,執行一次,觀察10次執行結果
4)所有請求都成功了,請求響應時間逐漸增加