使用Sentinel滑動窗口實現(xiàn)限流和降級
Sentinel滑動窗口前言
Sentinel 是一個開源的高可用性、高擴(kuò)展性的實時流量控制框架,它可以用于保護(hù)服務(wù)穩(wěn)定性,防止系統(tǒng)因為流量過大而崩潰。今天我們所介紹的,是滑動窗口,它是 Sentinel 實現(xiàn)限流和降級的重要組件之一。
Sentinel滑動窗口原理
滑動窗口通常由一個固定大小的時間窗口和一個可滑動的數(shù)據(jù)結(jié)構(gòu)組成,例如隊列或滑動塊。在 Sentinel 中,滑動窗口被分為計數(shù)器類型和預(yù)算類型:
計數(shù)器滑動窗口:計數(shù)器滑動窗口維護(hù)一個周期內(nèi)請求的總數(shù),當(dāng)周期結(jié)束后,滑動窗口會被清空,開始下一個周期的計數(shù)。在 Sentinel 中,計數(shù)器滑動窗口通過 AtomicLong 數(shù)組實現(xiàn),數(shù)組的長度代表時間窗口的大小,每個元素代表該時間片保存的請求次數(shù)。
預(yù)算滑動窗口:預(yù)算滑動窗口維護(hù)周期內(nèi)預(yù)算資源的使用情況,以便根據(jù)實際資源需要進(jìn)行限流或降級。預(yù)算類型的滑動窗口可以設(shè)置閾值,并支持動態(tài)調(diào)整。在 Sentinel 中,預(yù)算滑動窗口通常用于 CPU 使用率、線程池等容量資源的控制。
除此之外,Sentinel 還提供了基于單機(jī)、集群和分布式三種模式的滑動窗口實現(xiàn)。其中,單機(jī)模式下將使用本地內(nèi)存來維護(hù)滑動窗口數(shù)據(jù)結(jié)構(gòu);集群模式下,各節(jié)點會通過多播或 Redis 等方式共享相同的計數(shù)器數(shù)據(jù);分布式模式下,則允許多個服務(wù)節(jié)點公用同一組滑動窗口數(shù)據(jù)。
在使用 Sentinel 進(jìn)行限流和降級時,用戶可以通過配置規(guī)則來指定需要監(jiān)控的目標(biāo)資源,并設(shè)置相應(yīng)的閾值和處理策略。例如,在限流場景下,用戶可以設(shè)置最大 QPS,并指定超過該閾值的請求將會被丟棄或返回特定的錯誤碼。在降級場景下,用戶可以設(shè)置響應(yīng)時間、異常比例等閾值,并指定相應(yīng)的降級策略,例如返回默認(rèn)值或者直接拋出異常。
如何在項目中使用滑動窗口
以實際的項目為例子,我們有一個服務(wù)用于提供用戶信息查詢接口,每秒鐘最多只能處理 10 次查詢請求,并且如果連續(xù) 5 秒內(nèi)的請求次數(shù)超過 50 次,則觸發(fā)限流或降級操作。
在 Sentinel 中,我們首先需要定義一個 FlowRule 數(shù)組用于配置針對該服務(wù)的限流規(guī)則,在這塊項目例子中,它們是每秒鐘限流到 10 個請求和 5 秒內(nèi)超過 50 次請求兩種限制:
FlowRule rule1 = new FlowRule(); rule1.setResource("queryUser"); rule1.setCount(10); rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); FlowRule rule2 = new FlowRule(); rule2.setResource("queryUser"); rule2.setCount(50); rule2.setGrade(RuleConstant.FLOW_GRADE_QPS); rule2.setStrategy(RuleConstant.STRATEGY_CHAIN); rule2.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
我們先對以上代碼進(jìn)行解釋,“queryUser” 代表資源名稱,這個可以自己定義,然后設(shè)置了resource、count、grade以及對于第二個規(guī)則還增加了三個屬性stratety, controlBehavior和controlBehavior。其中 count 表示限流閾值,即每秒鐘最多可以處理多少個請求;grade 表示限流模式,QPS(每秒鐘最多允許通過的請求數(shù)量);strategy 表示限流策略;controlBehavior 表示流量控制的行為。
接下來,我們需要通過執(zhí)行如下代碼初始化 Sentinel:
List<FlowRule> rules = new ArrayList<>(); rules.add(rule1); rules.add(rule2); FlowRuleManager.loadRules(rules);
我們這里定義了一個 FlowRule 數(shù)組,將前面定義好的兩個規(guī)則加入到列表中,然后通過 FlowRuleManager.loadRules() 方法加載這些規(guī)則。
現(xiàn)在,我們可以在查詢用戶信息的方法上增加 @SentinelResource 注解,并在該注解中設(shè)置 blockHandler 和 fallback 屬性來處理限流和降級異常:
@SentinelResource(value = "queryUser", blockHandler = "queryUserBlockHandler", fallback = "queryUserFallback") public UserInfo queryUser(String userId) { // 查找用戶信息的實現(xiàn) } // 限流/降級處理函數(shù) public UserInfo queryUserBlockHandler(String userId, BlockException ex) { // 返回具體的錯誤信息 } // 降級處理 public UserInfo queryUserFallback(String userId, Throwable ex) { // 返回降級后的響應(yīng) }
以上代碼中我們定義了一個名為“queryUser”的資源,它被 @SentinelResource 注解所修飾,blockHandler 屬性表示當(dāng)該服務(wù)觸發(fā)限流或降級時調(diào)用的函數(shù),fallback 屬性表示服務(wù)出現(xiàn)異常時的回退函數(shù)。
最后,我們可以通過對定時任務(wù)進(jìn)行調(diào)度,模擬10秒內(nèi)對同一個 API 請求用戶數(shù)據(jù)的場景,例如代碼如下:
public class QueryUserTask implements Runnable { private static final Random random = new Random(); @Override public void run() { // 模擬 10 秒內(nèi)對同一個 API 請求用戶數(shù)據(jù) for (int i = 0; i < 20; i++) { String userId = "user-" + (i % 5); queryUser(userId); try { Thread.sleep(random.nextInt(500)); } catch (InterruptedException e) { e.printStackTrace(); } } } }
我們可以在 QueryUserTask 內(nèi)部實現(xiàn)每隔一秒獲取一次用戶信息,檢測系統(tǒng)是否觸發(fā)限流或降級保護(hù)。如果觸發(fā)了規(guī)則中配置的限流規(guī)則,那么 Sentinel 將執(zhí)行相應(yīng)的措施進(jìn)行處理。
好了,本篇文章就先分享到這里了,后續(xù)將會繼續(xù)介紹sentinel詳細(xì)的其他方面的知識。
到此這篇關(guān)于使用Sentinel滑動窗口實現(xiàn)限流和降級的文章就介紹到這了,更多相關(guān)Sentinel限流和降級內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis中一對多(collection)和一對一(association)的組合查詢使用
這篇文章主要介紹了Mybatis中一對多(collection)和一對一(association)的組合查詢使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12MyBatis XML去除多余AND|OR前綴或逗號等后綴的操作
這篇文章主要介紹了MyBatis XML去除多余AND|OR前綴或逗號等后綴的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02Java非靜態(tài)成員變量之死循環(huán)(詳解)
下面小編就為大家?guī)硪黄狫ava非靜態(tài)成員變量之死循環(huán)(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09RabbitMQ死信機(jī)制實現(xiàn)延遲隊列的實戰(zhàn)
本文主要介紹了RabbitMQ死信機(jī)制實現(xiàn)延遲隊列的實戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11SpringBoot熔斷機(jī)制之CircuitBreaker詳解
這篇文章主要介紹了SpringBoot熔斷機(jī)制之CircuitBreaker詳解,SpringBoot的熔斷機(jī)制在微服務(wù)架構(gòu)中扮演著重要角色,其中CircuitBreaker是其核心機(jī)制之一,用于防止服務(wù)的異常狀態(tài)影響到整個系統(tǒng)的運(yùn)作,需要的朋友可以參考下2023-10-10淺談spring和spring MVC的區(qū)別與關(guān)系
下面小編就為大家?guī)硪黄獪\談spring和spring MVC的區(qū)別與關(guān)系。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04基于springMvc+hibernate的web application的構(gòu)建
下面小編就為大家?guī)硪黄趕pringMvc+hibernate的web application的構(gòu)建。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10