偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Sentinel 流控規(guī)則詳解

開發(fā) 架構(gòu)
Sentinel 提供一個輕量級的開源控制臺,它提供機器發(fā)現(xiàn)以及健康情況管理、監(jiān)控(單機和集群),規(guī)則管理和推送的功能。這里,我們將會詳細(xì)講述如何通過簡單的步驟就可以使用這些功能。

[[399712]]

本文轉(zhuǎn)載自微信公眾號「運維開發(fā)故事」,作者老鄭。轉(zhuǎn)載本文請聯(lián)系運維開發(fā)故事公眾號。

在前面兩篇文章給大家介紹了 Sentinel 的功能和基本使用?,F(xiàn)在我們繼續(xù)來學(xué)習(xí) Sentinel 控制臺的基本使用,以及一些規(guī)則配置的說明。讓大家能夠在工作中使用 Sentinel 得心應(yīng)手 (大部分理論和描述來源于官方文檔和網(wǎng)絡(luò))。

在正文開始之前,我先說一下我的基本環(huán)境信息

  • jdk 1.8
  • sentinel 1.8.0
  • spring-boot 2.3.5.RELEASE
  • spring-cloud Hoxton.SR8
  • spring-cloud-alibaba 2.2.5.RELEASE

控制臺簡介

Sentinel 提供一個輕量級的開源控制臺,它提供機器發(fā)現(xiàn)以及健康情況管理、監(jiān)控(單機和集群),規(guī)則管理和推送的功能。這里,我們將會詳細(xì)講述如何通過簡單的步驟就可以使用這些功能。

Sentinel 控制臺包含如下功能:

  • 查看機器列表以及健康情況:收集 Sentinel 客戶端發(fā)送的心跳包,用于判斷機器是否在線。
  • 監(jiān)控 (單機和集群聚合):通過 Sentinel 客戶端暴露的監(jiān)控 API,定期拉取并且聚合應(yīng)用監(jiān)控信息,最終可以實現(xiàn)秒級的實時監(jiān)控。
  • 規(guī)則管理和推送:統(tǒng)一管理推送規(guī)則。
  • 鑒權(quán):生產(chǎn)環(huán)境中鑒權(quán)非常重要。這里每個開發(fā)者需要根據(jù)自己的實際情況進(jìn)行定制。

注意:Sentinel 控制臺目前僅支持單機部署。Sentinel 控制臺項目提供 Sentinel 功能全集示例,不作為開箱即用的生產(chǎn)環(huán)境控制臺,若希望在生產(chǎn)環(huán)境使用需要自行定制和改造。

Alibaba 提供了企業(yè)版本的 Sentinel 我們可以在 aliyun.com 上面購買 AHAS Sentinel

查看機器列表以及健康情況

如果我們正確的接入 Sentinel 之后我們可以在 Sentinel 控制臺的 機器列表 菜單中來查看我們服務(wù)節(jié)點的健康情況

如果 Sentinel 接入不成功,可以查閱 Sentinel 官方文檔或者 FAQ 來對應(yīng)排查

服務(wù)監(jiān)控

1. 實時監(jiān)控

同時,同一個服務(wù)下的所有機器的簇點信息會被匯總,并且秒級地展示在"實時監(jiān)控"下。

注意: 實時監(jiān)控僅存儲 5 分鐘以內(nèi)的數(shù)據(jù),如果需要持久化,需要通過調(diào)用實時監(jiān)控接口來定制。

注意:請確保 Sentinel 控制臺所在的機器時間與自己應(yīng)用的機器時間保持一致,否則會導(dǎo)致拉不到實時的監(jiān)控數(shù)據(jù)。

2. 簇點鏈路

簇點鏈路(單機調(diào)用鏈路)頁面實時的去拉取指定客戶端資源的運行情況。它一共提供兩種展示模式:一種用樹狀結(jié)構(gòu)展示資源的調(diào)用鏈路,另外一種則不區(qū)分調(diào)用鏈路展示資源的實時情況。

注意: 簇點鏈路監(jiān)控是內(nèi)存態(tài)的信息,它僅展示啟動后調(diào)用過的資源。

注意:請確保 Sentinel 控制臺所在的機器時間與自己應(yīng)用的機器時間保持一致,否則會導(dǎo)致拉不到實時的監(jiān)控數(shù)據(jù)。

3 流控規(guī)則

流量控制(flow control),其原理是監(jiān)控應(yīng)用流量的 QPS 或并發(fā)線程數(shù)等指標(biāo),當(dāng)達(dá)到指定的閾值時對流量進(jìn)行控制,以避免被瞬時的流量高峰沖垮,從而保障應(yīng)用的高可用性。

FlowSlot 會根據(jù)預(yù)設(shè)的規(guī)則,結(jié)合 NodeSelectorSlot、ClusterBuilderSlot、StatisticSlot 統(tǒng)計出來的實時信息進(jìn)行流量控制。

限流的直接表現(xiàn)是在執(zhí)行 Entry nodeA = SphU.entry(resourceName) 的時候拋出 FlowException 異常。FlowException 是 BlockException 的子類,您可以捕捉 BlockException 來自定義被限流之后的處理邏輯。

Sentinel 在觸發(fā)規(guī)則保護(hù)時,返回的異常頁面是一樣的。不好區(qū)分是因為哪種規(guī)則導(dǎo)致的異常。所以需要自定義異常返回信息,明確是觸發(fā)了哪種類型的規(guī)則。

  1. @Component 
  2. public class SentinelBlockHandler implements BlockExceptionHandler { 
  3.     @Override 
  4.     public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, 
  5.                        BlockException e) throws Exception { 
  6.         CommonResult<Void> result = new CommonResult<>(); 
  7.         if (e instanceof FlowException) { 
  8.             result = CommonResult.error(101, "接口限流了"); 
  9.         } else if (e instanceof DegradeException) { 
  10.             result = CommonResult.error(102, "服務(wù)降級了"); 
  11.         } else if (e instanceof ParamFlowException) { 
  12.             result = CommonResult.error(103, "熱點參數(shù)限流了"); 
  13.         } else if (e instanceof SystemBlockException) { 
  14.             result = CommonResult.error(104, "系統(tǒng)規(guī)則(負(fù)載/...不滿足要求)"); 
  15.         } else if (e instanceof AuthorityException) { 
  16.             result = CommonResult.error(105, "授權(quán)規(guī)則不通過"); 
  17.         } 
  18.         // http狀態(tài)碼 
  19.         httpServletResponse.setStatus(500); 
  20.         httpServletResponse.setCharacterEncoding("utf-8"); 
  21.         httpServletResponse.setHeader("Content-Type""application/json;charset=utf-8"); 
  22.         httpServletResponse.setContentType("application/json;charset=utf-8"); 
  23.         // spring mvc自帶的json操作工具,叫jackson 
  24.         new ObjectMapper().writeValue(httpServletResponse.getWriter(), result); 
  25.     } 

效果如下:

  1. ➜ curl http://127.0.0.1:8088/getStockDetail 
  2. {"code":1,"message":"this is a success message","data":{"id":1,"code":"STOCK==>1000"}}%                                                       ➜ curl http://127.0.0.1:8088/getStockDetail 
  3. {"code":1,"message":"this is a success message","data":{"id":1,"code":"STOCK==>1000"}}%                                                        ➜ curl http://127.0.0.1:8088/getStockDetail 
  4. {"code":101,"message":"接口限流了","data":null}% 

閾值類型

線程數(shù)

并發(fā)數(shù)控制用于保護(hù)業(yè)務(wù)線程池不被慢調(diào)用耗盡。例如,當(dāng)應(yīng)用所依賴的下游應(yīng)用由于某種原因?qū)е路?wù)不穩(wěn)定、響應(yīng)延遲增加,對于調(diào)用者來說,意味著吞吐量下降和更多的線程數(shù)占用,極端情況下甚至導(dǎo)致線程池耗盡。為應(yīng)對太多線程占用的情況,業(yè)內(nèi)有使用隔離的方案,比如通過不同業(yè)務(wù)邏輯使用不同線程池來隔離業(yè)務(wù)自身之間的資源爭搶(線程池隔離)。這種隔離方案雖然隔離性比較好,但是代價就是線程數(shù)目太多,線程上下文切換的 overhead 比較大,特別是對低延時的調(diào)用有比較大的影響。Sentinel 并發(fā)控制不負(fù)責(zé)創(chuàng)建和管理線程池,而是簡單統(tǒng)計當(dāng)前請求上下文的線程數(shù)目(正在執(zhí)行的調(diào)用數(shù)目),如果超出閾值,新的請求會被立即拒絕,效果類似于信號量隔離。并發(fā)數(shù)控制通常在調(diào)用端進(jìn)行配置。

可以通過線程池模擬客戶端調(diào)用, 也可以通過 Jmeter 模擬,觸發(fā)流控的結(jié)果如下:

  1. ➜  ~ curl http://127.0.0.1:8088/getStockDetail 
  2. {"code":101,"message":"接口限流了","data":null}% 

流控模式

調(diào)用關(guān)系包括調(diào)用方、被調(diào)用方;一個方法又可能會調(diào)用其它方法,形成一個調(diào)用鏈路的層次關(guān)系。

直接

當(dāng)資源觸發(fā)流控規(guī)則過后直接,拋出異常信息

  1. ➜  ~ curl http://127.0.0.1:8088/getStockDetail 
  2. {"code":101,"message":"接口限流了","data":null}% 

關(guān)聯(lián)

當(dāng)兩個資源之間具有資源爭搶或者依賴關(guān)系的時候,這兩個資源便具有了關(guān)聯(lián)。比如對數(shù)據(jù)庫同一個字段的讀操作和寫操作存在爭搶,讀的速度過高會影響寫的速度,寫的速度過高會影響讀的速度。如果放任讀寫操作爭搶資源,則爭搶本身帶來的開銷會降低整體的吞吐量??墒褂藐P(guān)聯(lián)限流來避免具有關(guān)聯(lián)關(guān)系的資源之間過度的爭搶,舉例來說,read_db 和 write_db 這兩個資源分別代表數(shù)據(jù)庫讀寫,我們可以給 read_db 設(shè)置限流規(guī)則來達(dá)到寫優(yōu)先的目的:設(shè)置 strategy 為 RuleConstant.STRATEGY_RELATE 同時設(shè)置 refResource 為 write_db。這樣當(dāng)寫庫操作過于頻繁時,讀數(shù)據(jù)的請求會被限流。

如果配置流控規(guī)則為關(guān)聯(lián)模式,那么當(dāng) /hello 接口超過閾值過后,就會對 /getStockDetail 接口觸發(fā)流控規(guī)則。

鏈路

NodeSelectorSlot 中記錄了資源之間的調(diào)用鏈路,這些資源通過調(diào)用關(guān)系,相互之間構(gòu)成一棵調(diào)用樹。這棵樹的根節(jié)點是一個名字為 machine-root 的虛擬節(jié)點,調(diào)用鏈的入口都是這個虛節(jié)點的子節(jié)點。

一棵典型的調(diào)用樹如下圖所示:

  1. machine-root 
  2.                    /       \ 
  3.                   /         \ 
  4.             Entrance1     Entrance2 
  5.                /             \ 
  6.               /               \ 
  7.      DefaultNode(nodeA)   DefaultNode(nodeA) 

上圖中來自入口 Entrance1 和 Entrance2 的請求都調(diào)用到了資源 NodeA,Sentinel 允許只根據(jù)某個入口的統(tǒng)計信息對資源限流。比如我們可以設(shè)置 strategy 為 RuleConstant.STRATEGY_CHAIN,同時設(shè)置 refResource 為 Entrance1 來表示只有從入口 Entrance1 的調(diào)用才會記錄到 NodeA 的限流統(tǒng)計當(dāng)中,而不關(guān)心經(jīng) Entrance2 到來的調(diào)用。

調(diào)用鏈的入口(上下文)是通過 API 方法 ContextUtil.enter(contextName) 定義的,其中 contextName 即對應(yīng)調(diào)用鏈路入口名稱。詳情可以參考 ContextUtil 文檔。]

測試會發(fā)現(xiàn) 鏈路 不會生效

從1.6.3版本開始,Sentinel Web filter默認(rèn)收斂所有URL的入口context,因此鏈路限流不生效。1.7.0版本開始(對應(yīng)SCA 2.1.1.RELEASE),我們在CommonFilter引入了WEB_CONTEXT_UNIFY這個init parameter,用于控制是否收斂context。將其配置為false即可根據(jù)不同的URL進(jìn)行鏈路限流。參考:https://github.com/alibaba/sentinel/issues/1213

解決方案:

1.7.0 版本開始(對應(yīng)Spring Cloud Alibaba的2.1.1.RELEASE) 需要新增依賴

  1. @Configuration 
  2. public class FilterContextConfig { 
  3.     @Bean 
  4.     public FilterRegistrationBean sentinelFilterRegistration() { 
  5.         FilterRegistrationBean registration = new FilterRegistrationBean(); 
  6.         registration.setFilter(new CommonFilter()); 
  7.         registration.addUrlPatterns("/*"); 
  8.          
  9.         // 入口資源關(guān)閉聚合 
  10.         registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false"); 
  11.         registration.setName("sentinelFilter"); 
  12.         registration.setOrder(1); 
  13.         return registration; 
  14.     } 

然后我們再嘗試觸發(fā)流控規(guī)則, 對 /getStockDetail 進(jìn)行訪問,這里返回了FlowException

默認(rèn)情況會返回

如果我們使用 OpenFeign 不添加 fallbackFactory 就會返回500 , 如果我們添加了就可以避免這個問題。

  1. // Controller 
  2. @Autowired 
  3. private StockFeign stockFeign; 
  4. @GetMapping("/getStockDetail"
  5. public CommonResult<StockModel> getStockDetail() { 
  6.   CommonResult<StockModel> result = stockFeign.getStockDetail(); 
  7.   if (result.getCode() != 1) { 
  8.     return CommonResult.error(null, result.getCode(), result.getMessage()); 
  9.   } 
  10.   return result; 
  11. // FeignClient 
  12. @FeignClient(name = "stock-service"
  13.         //, fallbackFactory = StockFeignFallbackFactory.class) 
  14. public interface StockFeign { 
  15.     @GetMapping("/getStockDetail"
  16.     CommonResult<StockModel> getStockDetail(); 

Sentinel 部分源碼:

所以,我們在設(shè)置鏈路流控規(guī)則的時候一定要設(shè)置 fallbackFactory。不然無法處理 FlowExecption 異常信息,造成系統(tǒng)出錯。對于個人而言,Sentinel 的鏈路規(guī)則比不是特別的好用,無特殊要求,不建議使用,或者選擇Sentinel 的收費版本 AHAS

流控效果

當(dāng) QPS、線程數(shù)超過某個閾值的時候,則采取措施進(jìn)行流量控制。流量控制的效果包括以下幾種:直接拒絕、Warm Up、勻速排隊。

直接拒絕

直接拒絕(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)方式是默認(rèn)的流量控制方式,當(dāng)QPS超過任意規(guī)則的閾值后,新的請求就會被立即拒絕,拒絕方式為拋出FlowException。 這種方式適用于對系統(tǒng)處理能力確切已知的情況下,比如通過壓測確定了系統(tǒng)的準(zhǔn)確水位時。

Warm up

Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即預(yù)熱/冷啟動方式。當(dāng)系統(tǒng)長期處于低水位的情況下,當(dāng)流量突然增加時,直接把系統(tǒng)拉升到高水位可能瞬間把系統(tǒng)壓垮。通過"冷啟動",讓通過的流量緩慢增加,在一定時間內(nèi)逐漸增加到閾值上限,給冷系統(tǒng)一個預(yù)熱的時間,避免冷系統(tǒng)被壓垮。

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

默認(rèn) coldFactor 為 3,即請求 QPS 從 threshold / 3 開始,經(jīng)預(yù)熱時長逐漸升至設(shè)定的 QPS 閾值。

規(guī)則設(shè)置如下圖所示:

通過 Jmeter 請求過后,可以看到如下效果,完成流控

勻速排隊

勻速排隊(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式會嚴(yán)格控制請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應(yīng)的是漏桶算法。

這種方式主要用于處理間隔性突發(fā)的流量,例如消息隊列。想象一下這樣的場景,在某一秒有大量的請求到來,而接下來的幾秒則處于空閑狀態(tài),我們希望系統(tǒng)能夠在接下來的空閑期間逐漸處理這些請求,而不是在第一秒直接拒絕多余的請求。

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

規(guī)則設(shè)置如下圖所示:

然后我們通過 jmeter 請求過后可以看到如下效果:

4. 降級規(guī)則

流量控制以外,對調(diào)用鏈路中不穩(wěn)定的資源進(jìn)行熔斷降級也是保障高可用的重要措施之一。一個服務(wù)常常會調(diào)用別的模塊,可能是另外的一個遠(yuǎn)程服務(wù)、數(shù)據(jù)庫,或者第三方 API 等。例如,支付的時候,可能需要遠(yuǎn)程調(diào)用銀聯(lián)提供的 API;查詢某個商品的價格,可能需要進(jìn)行數(shù)據(jù)庫查詢。然而,這個被依賴服務(wù)的穩(wěn)定性是不能保證的。如果依賴的服務(wù)出現(xiàn)了不穩(wěn)定的情況,請求的響應(yīng)時間變長,那么調(diào)用服務(wù)的方法的響應(yīng)時間也會變長,線程會產(chǎn)生堆積,最終可能耗盡業(yè)務(wù)自身的線程池,服務(wù)本身也變得不可用。

熔斷降級策略

Sentinel 提供以下幾種熔斷策略:

  • 慢調(diào)用比例 (SLOW_REQUEST_RATIO):選擇以慢調(diào)用比例作為閾值,需要設(shè)置允許的慢調(diào)用 RT(即最大的響應(yīng)時間),請求的響應(yīng)時間大于該值則統(tǒng)計為慢調(diào)用。當(dāng)單位統(tǒng)計時長(statIntervalMs)內(nèi)請求數(shù)目大于設(shè)置的最小請求數(shù)目,并且慢調(diào)用的比例大于閾值,則接下來的熔斷時長內(nèi)請求會自動被熔斷。經(jīng)過熔斷時長后熔斷器會進(jìn)入探測恢復(fù)狀態(tài)(HALF-OPEN 狀態(tài)),若接下來的一個請求響應(yīng)時間小于設(shè)置的慢調(diào)用 RT 則結(jié)束熔斷,若大于設(shè)置的慢調(diào)用 RT 則會再次被熔斷。

我們可以在控制臺配置:

jmeter 模擬請求

異常比例 (ERROR_RATIO):當(dāng)單位統(tǒng)計時長(statIntervalMs)內(nèi)請求數(shù)目大于設(shè)置的最小請求數(shù)目,并且異常的比例大于閾值,則接下來的熔斷時長內(nèi)請求會自動被熔斷。經(jīng)過熔斷時長后熔斷器會進(jìn)入探測恢復(fù)狀態(tài)(HALF-OPEN 狀態(tài)),若接下來的一個請求成功完成(沒有錯誤)則結(jié)束熔斷,否則會再次被熔斷。異常比率的閾值范圍是 [0.0, 1.0],代表 0% - 100%。

我們可以在控制臺配置:

  • 異常數(shù) (ERROR_COUNT):當(dāng)單位統(tǒng)計時長內(nèi)的異常數(shù)目超過閾值之后會自動進(jìn)行熔斷。經(jīng)過熔斷時長后熔斷器會進(jìn)入探測恢復(fù)狀態(tài)(HALF-OPEN 狀態(tài)),若接下來的一個請求成功完成(沒有錯誤)則結(jié)束熔斷,否則會再次被熔斷。

我們可以在控制臺配置:

熔斷降級說明

熔斷降級規(guī)則(DegradeRule)包含下面幾個重要的屬性:

 

Field

說明

默認(rèn)值

resource

資源名,即規(guī)則的作用對象

 

grade

熔斷策略,支持慢調(diào)用比例/異常比例/異常數(shù)策略

慢調(diào)用比例

count

慢調(diào)用比例模式下為慢調(diào)用臨界 RT(超出該值計為慢調(diào)用);異常比例/異常數(shù)模式下為對應(yīng)的閾值

 

timeWindow

熔斷時長,單位為 s

 

minRequestAmount

熔斷觸發(fā)的最小請求數(shù),請求數(shù)小于該值時即使異常比率超出閾值也不會熔斷(1.7.0 引入)

5

statIntervalMs

統(tǒng)計時長(單位為 ms),如 60*1000 代表分鐘級(1.8.0 引入)

1000 ms

slowRatioThreshold

慢調(diào)用比例閾值,僅慢調(diào)用比例模式有效(1.8.0 引入)

5. 熱點規(guī)則

何為熱點?熱點即經(jīng)常訪問的數(shù)據(jù)。很多時候我們希望統(tǒng)計某個熱點數(shù)據(jù)中訪問頻次最高的 Top K 數(shù)據(jù),并對其訪問進(jìn)行限制。比如:

  • 商品 ID 為參數(shù),統(tǒng)計一段時間內(nèi)最常購買的商品 ID 并進(jìn)行限制
  • 用戶 ID 為參數(shù),針對一段時間內(nèi)頻繁訪問的用戶 ID 進(jìn)行限制

熱點參數(shù)限流會統(tǒng)計傳入?yún)?shù)中的熱點參數(shù),并根據(jù)配置的限流閾值與模式,對包含熱點參數(shù)的資源調(diào)用進(jìn)行限流。熱點參數(shù)限流可以看做是一種特殊的流量控制,僅對包含熱點參數(shù)的資源調(diào)用生效。

Sentinel 利用 LRU 策略統(tǒng)計最近最常訪問的熱點參數(shù),結(jié)合令牌桶算法來進(jìn)行參數(shù)級別的流控。熱點參數(shù)限流支持集群模式。

熱點規(guī)則配置需要注意:

1. 首先資源必須是通過 @SentinelResource 申明

2. 參數(shù)類型必須是基礎(chǔ)數(shù)據(jù)類型, 否則配置無效

熱點規(guī)則配置如下圖所示:

注意:資源名稱要和 @SentinelResource 中的資源名稱對應(yīng)才能生效

控制器類的代碼如下所示:

  1. @SentinelResource(value = "ResOrderGet"
  2.                   fallback = "fallback"
  3.                   fallbackClass = SentinelExceptionHandler.class, 
  4.                   blockHandler = "blockHandler"
  5.                   blockHandlerClass = SentinelExceptionHandler.class 
  6.                  ) 
  7. @GetMapping("/order/get/{id}"
  8. public CommonResult<StockModel> getStockDetails(@PathVariable Integer id) { 
  9.   StockModel stockModel = new StockModel(); 
  10.   stockModel.setCode("STOCK==>1000"); 
  11.   stockModel.setId(id); 
  12.   return CommonResult.success(stockModel); 
  13. // 異常處理類 
  14. public class SentinelResourceExceptionHandler { 
  15.     //限流熔斷業(yè)務(wù)邏輯 
  16.     public static CommonResult<StockModel> blockHandler(@PathVariable Integer id) { 
  17.         return CommonResult.error(null, -100, "系統(tǒng)錯誤 (限流熔斷業(yè)務(wù)邏輯)"); 
  18.     } 
  19.     //異常降級業(yè)務(wù)邏輯 
  20.     public static CommonResult<StockModel> fallback(@PathVariable Integer id) { 
  21.         return CommonResult.error(null, -100, "系統(tǒng)錯誤 (異常降級業(yè)務(wù)邏輯)"); 
  22.     } 

返回異常信息:

6 授權(quán)規(guī)則

很多時候,我們需要根據(jù)調(diào)用來源來判斷該次請求是否允許放行,這時候可以使用 Sentinel 的來源訪問控制(黑白名單控制)的功能。來源訪問控制根據(jù)資源的請求來源(origin)限制資源是否通過,若配置白名單則只有請求來源位于白名單內(nèi)時才可通過;若配置黑名單則請求來源位于黑名單時不通過,其余的請求通過。

調(diào)用方信息通過 ContextUtil.enter(resourceName, origin) 方法中的 origin 參數(shù)傳入。

Sentinel提供了 RequestOriginParser 接口來處理訪問來源,Sentinel保護(hù)的資源如果被訪問,就會調(diào)用 RequestOriginParser解析訪問來源。

  1. // 注意導(dǎo)包 
  2. import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser; 
  3. import javax.servlet.http.HttpServletRequest; 
  4. public class SentinelRequestOriginParser implements RequestOriginParser { 
  5.     @Override 
  6.     public String parseOrigin(HttpServletRequest request) { 
  7.         return request.getParameter("origin"); 
  8.     } 

修改 Config 配置信息

  1. @Configuration 
  2. public class FilterContextConfig { 
  3.     @Bean 
  4.     public FilterRegistrationBean sentinelFilterRegistration() { 
  5.         FilterRegistrationBean registration = new FilterRegistrationBean(); 
  6.         registration.setFilter(new CommonFilter()); 
  7.         registration.addUrlPatterns("/*"); 
  8.         // 入口資源關(guān)閉聚合 
  9.         registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false"); 
  10.         registration.setName("sentinelFilter"); 
  11.         registration.setOrder(1); 
  12.         // CommonFilter 的 BlockException 自定義處理邏輯 
  13.         WebCallbackManager.setUrlBlockHandler(new SentinelFlowHandler()); 
  14.         //解決授權(quán)規(guī)則不生效的問題 
  15.         //com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser 
  16.         WebCallbackManager.setRequestOriginParser(new SentinelRequestOriginParser()); 
  17.         return registration; 
  18.     } 

規(guī)則配置

執(zhí)行請求

正常通過

異常不通過

7 系統(tǒng)規(guī)則

系統(tǒng)保護(hù)規(guī)則是從應(yīng)用級別的入口流量進(jìn)行控制,從單臺機器的 load、CPU 使用率、平均 RT、入口 QPS 和并發(fā)線程數(shù)等幾個維度監(jiān)控應(yīng)用指標(biāo),讓系統(tǒng)盡可能跑在最大吞吐量的同時保證系統(tǒng)整體的穩(wěn)定性。

系統(tǒng)保護(hù)規(guī)則是應(yīng)用整體維度的,而不是資源維度的,并且僅對入口流量生效。入口流量指的是進(jìn)入應(yīng)用的流量(EntryType.IN),比如 Web 服務(wù)或 Dubbo 服務(wù)端接收的請求,都屬于入口流量。

系統(tǒng)規(guī)則支持以下的模式:

  • Load 自適應(yīng)(僅對 Linux/Unix-like 機器生效):系統(tǒng)的 load1 作為啟發(fā)指標(biāo),進(jìn)行自適應(yīng)系統(tǒng)保護(hù)。當(dāng)系統(tǒng) load1 超過設(shè)定的啟發(fā)值,且系統(tǒng)當(dāng)前的并發(fā)線程數(shù)超過估算的系統(tǒng)容量時才會觸發(fā)系統(tǒng)保護(hù)(BBR 階段)。系統(tǒng)容量由系統(tǒng)的 maxQps * minRt 估算得出。設(shè)定參考值一般是 CPU cores * 2.5。
  • CPU usage(1.5.0+ 版本):當(dāng)系統(tǒng) CPU 使用率超過閾值即觸發(fā)系統(tǒng)保護(hù)(取值范圍 0.0-1.0),比較靈敏。
  • 平均 RT:當(dāng)單臺機器上所有入口流量的平均 RT 達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù),單位是毫秒。
  • 并發(fā)線程數(shù):當(dāng)單臺機器上所有入口流量的并發(fā)線程數(shù)達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)。
  • 入口 QPS:當(dāng)單臺機器上所有入口流量的 QPS 達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)。

原理

如下圖所示

我們把系統(tǒng)處理請求的過程想象為一個水管,到來的請求是往這個水管灌水,當(dāng)系統(tǒng)處理順暢的時候,請求不需要排隊,直接從水管中穿過,這個請求的RT是最短的;反之,當(dāng)請求堆積的時候,那么處理請求的時間則會變?yōu)椋号抨爼r間 + 最短處理時間。

  • 推論一: 如果我們能夠保證水管里的水量,能夠讓水順暢的流動,則不會增加排隊的請求;也就是說,這個時候的系統(tǒng)負(fù)載不會進(jìn)一步惡化。

我們用 T 來表示(水管內(nèi)部的水量),用RT來表示請求的處理時間,用P來表示進(jìn)來的請求數(shù),那么一個請求從進(jìn)入水管道到從水管出來,這個水管會存在 P * RT 個請求。換一句話來說,當(dāng) T ≈ QPS * Avg(RT) 的時候,我們可以認(rèn)為系統(tǒng)的處理能力和允許進(jìn)入的請求個數(shù)達(dá)到了平衡,系統(tǒng)的負(fù)載不會進(jìn)一步惡化。

接下來的問題是,水管的水位是可以達(dá)到了一個平衡點,但是這個平衡點只能保證水管的水位不再繼續(xù)增高,但是還面臨一個問題,就是在達(dá)到平衡點之前,這個水管里已經(jīng)堆積了多少水。如果之前水管的水已經(jīng)在一個量級了,那么這個時候系統(tǒng)允許通過的水量可能只能緩慢通過,RT會大,之前堆積在水管里的水會滯留;反之,如果之前的水管水位偏低,那么又會浪費了系統(tǒng)的處理能力。

  • 推論二: 當(dāng)保持入口的流量是水管出來的流量的最大的值的時候,可以最大利用水管的處理能力。

然而,和 TCP BBR 的不一樣的地方在于,還需要用一個系統(tǒng)負(fù)載的值(load1)來激發(fā)這套機制啟動。

注:這種系統(tǒng)自適應(yīng)算法對于低 load 的請求,它的效果是一個“兜底”的角色。對于不是應(yīng)用本身造成的 load 高的情況(如其它進(jìn)程導(dǎo)致的不穩(wěn)定的情況),效果不明顯。

配置頁面

觸發(fā)流控規(guī)則

8 集群流控

為什么要使用集群流控呢?假設(shè)我們希望給某個用戶限制調(diào)用某個 API 的總 QPS 為 50,但機器數(shù)可能很多(比如有 100 臺)。這時候我們很自然地就想到,找一個 server 來專門來統(tǒng)計總的調(diào)用量,其它的實例都與這臺 server 通信來判斷是否可以調(diào)用。這就是最基礎(chǔ)的集群流控的方式。

另外集群流控還可以解決流量不均勻?qū)е驴傮w限流效果不佳的問題。假設(shè)集群中有 10 臺機器,我們給每臺機器設(shè)置單機限流閾值為 10 QPS,理想情況下整個集群的限流閾值就為 100 QPS。不過實際情況下流量到每臺機器可能會不均勻,會導(dǎo)致總量沒有到的情況下某些機器就開始限流。因此僅靠單機維度去限制的話會無法精確地限制總體流量。而集群流控可以精確地控制整個集群的調(diào)用總量,結(jié)合單機限流兜底,可以更好地發(fā)揮流量控制的效果。

集群流控中共有兩種身份:

  • Token Client:集群流控客戶端,用于向所屬 Token Server 通信請求 token。集群限流服務(wù)端會返回給客戶端結(jié)果,決定是否限流。
  • Token Server:即集群流控服務(wù)端,處理來自 Token Client 的請求,根據(jù)配置的集群規(guī)則判斷是否應(yīng)該發(fā)放 token(是否允許通過)。

規(guī)則推送

Sentinel 控制臺同時提供簡單的規(guī)則管理以及推送的功能。規(guī)則推送分為 3 種模式,包括 "原始模式"、"Pull 模式" 和"Push 模式"。

這里先簡單的介紹"原始模式"。

規(guī)則管理

您可以在控制臺通過接入端暴露的 HTTP API 來查詢規(guī)則。

規(guī)則推送

目前控制臺的規(guī)則推送也是通過 規(guī)則查詢更改 HTTP API 來更改規(guī)則。這也意味著這些規(guī)則僅在內(nèi)存態(tài)生效,應(yīng)用重啟之后,該規(guī)則會丟失。

注:若通過控制臺推送規(guī)則時出現(xiàn) invalid type 或 empty type 的錯誤,請確保 transport 模塊版本與 core 模塊版本保持一致;若控制臺版本 >= 1.7.1,請將接入端的相關(guān)依賴也升級至 1.7.1 及以上版本。

以上是原始模式。當(dāng)了解了原始模式之后,我們非常鼓勵您通過 動態(tài)規(guī)則 并結(jié)合各種外部存儲來定制自己的規(guī)則源。我們推薦通過動態(tài)配置源的控制臺來進(jìn)行規(guī)則寫入和推送,而不是通過 Sentinel 客戶端直接寫入到動態(tài)配置源中。在生產(chǎn)環(huán)境中,我們推薦 push 模式,具體可以參考:在生產(chǎn)環(huán)境使用 Sentinel。

注:若要使用集群流控功能,則必須對接動態(tài)規(guī)則源,否則無法正常使用。您也可以接入 AHAS Sentinel 快速接入全自動托管、高可用的集群流控能力。

Sentinel 同時還提供應(yīng)用維度規(guī)則推送的示例頁面(流控規(guī)則頁面,前端路由為 /v2/flow),用戶改造控制臺對接配置中心后可直接通過 v2 頁面推送規(guī)則至配置中心。Sentinel 抽取了通用接口用于向遠(yuǎn)程配置中心推送規(guī)則以及拉取規(guī)則:

DynamicRuleProvider: 拉取規(guī)則(應(yīng)用維度)

DynamicRulePublisher: 推送規(guī)則(應(yīng)用維度)

用戶只需實現(xiàn) DynamicRuleProvider 和 DynamicRulePublisher 接口,并在 v2 的 controller 中通過 @Qualifier 注解替換相應(yīng)的 bean 即可實現(xiàn)應(yīng)用維度推送。我們提供了 Nacos 和 Apollo 的示例,改造詳情可參考 應(yīng)用維度規(guī)則推送示例。

鑒權(quán)

從 Sentinel 1.5.0 開始,控制臺提供通用的鑒權(quán)接口 AuthService,用戶可根據(jù)需求自行實現(xiàn)。

從 Sentinel 1.6.0 起,Sentinel 控制臺引入基本的登錄功能,默認(rèn)用戶名和密碼都是 sentinel。該鑒權(quán)能力非?;A(chǔ),生產(chǎn)環(huán)境使用建議根據(jù)安全需要自行改造。

用戶可以通過如下參數(shù)進(jìn)行配置:

  • -Dsentinel.dashboard.auth.username=sentinel 用于指定控制臺的登錄用戶名為 sentinel;
  • -Dsentinel.dashboard.auth.password=123456 用于指定控制臺的登錄密碼為 123456;如果省略這兩個參數(shù),默認(rèn)用戶和密碼均為 sentinel;
  • -Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服務(wù)端 session 的過期時間,如 7200 表示 7200 秒;60m 表示 60 分鐘,默認(rèn)為 30 分鐘;

同樣也可以直接在 Spring properties 文件中進(jìn)行配置。

注意:部署多臺控制臺時,session 默認(rèn)不會在各實例之間共享,這一塊需要自行改造。

參考文檔

 

https://github.com/alibaba/Sentinel/wiki/控制臺

 

責(zé)任編輯:武曉燕 來源: 運維開發(fā)故事
相關(guān)推薦

2022-05-25 08:42:32

sentinel流控規(guī)則

2021-05-24 08:09:21

SentinelRedis 流控原理

2021-05-14 07:45:07

Sentinel 接口限流

2021-05-25 08:01:55

SentinelRedis 流控算法

2025-02-03 00:55:00

Sentinel分布式系統(tǒng)

2021-05-20 08:01:15

Nacos 存儲Sentinel

2012-05-08 13:18:42

流控引擎流控

2024-04-28 18:24:05

2022-05-29 21:38:11

限流熔斷流量

2021-05-21 08:30:26

Sentinel GateWay 微服務(wù)

2011-03-23 10:13:09

高校流控設(shè)備網(wǎng)康科技

2010-11-11 14:05:17

SQL Server排

2023-06-15 09:45:14

智能技術(shù)

2013-01-28 14:56:07

飛魚星無線路由器WLAN

2013-04-25 14:44:28

飛魚星無線路由器Wi-Fi

2021-03-23 15:50:53

微服務(wù)架構(gòu)互聯(lián)網(wǎng)

2009-12-04 16:20:49

2022-04-22 08:48:51

AQE流控架構(gòu)

2013-01-21 12:34:41

點贊
收藏

51CTO技術(shù)棧公眾號