自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Sentinel 流控規(guī)則詳解

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

[[399712]]

本文轉(zhuǎn)載自微信公眾號(hào)「運(yùn)維開(kāi)發(fā)故事」,作者老鄭。轉(zhuǎn)載本文請(qǐng)聯(lián)系運(yùn)維開(kāi)發(fā)故事公眾號(hào)。

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

在正文開(kāi)始之前,我先說(shuō)一下我的基本環(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

控制臺(tái)簡(jiǎn)介

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

Sentinel 控制臺(tái)包含如下功能:

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

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

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

查看機(jī)器列表以及健康情況

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

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

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

1. 實(shí)時(shí)監(jiān)控

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

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

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

2. 簇點(diǎn)鏈路

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

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

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

3 流控規(guī)則

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

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

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

Sentinel 在觸發(fā)規(guī)則保護(hù)時(shí),返回的異常頁(yè)面是一樣的。不好區(qū)分是因?yàn)槟姆N規(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ù)降級(jí)了"); 
  11.         } else if (e instanceof ParamFlowException) { 
  12.             result = CommonResult.error(103, "熱點(diǎn)參數(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ī)則不通過(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)延遲增加,對(duì)于調(diào)用者來(lái)說(shuō),意味著吞吐量下降和更多的線程數(shù)占用,極端情況下甚至導(dǎo)致線程池耗盡。為應(yīng)對(duì)太多線程占用的情況,業(yè)內(nèi)有使用隔離的方案,比如通過(guò)不同業(yè)務(wù)邏輯使用不同線程池來(lái)隔離業(yè)務(wù)自身之間的資源爭(zhēng)搶(線程池隔離)。這種隔離方案雖然隔離性比較好,但是代價(jià)就是線程數(shù)目太多,線程上下文切換的 overhead 比較大,特別是對(duì)低延時(shí)的調(diào)用有比較大的影響。Sentinel 并發(fā)控制不負(fù)責(zé)創(chuàng)建和管理線程池,而是簡(jiǎn)單統(tǒng)計(jì)當(dāng)前請(qǐng)求上下文的線程數(shù)目(正在執(zhí)行的調(diào)用數(shù)目),如果超出閾值,新的請(qǐng)求會(huì)被立即拒絕,效果類似于信號(hào)量隔離。并發(fā)數(shù)控制通常在調(diào)用端進(jìn)行配置。

可以通過(guò)線程池模擬客戶端調(diào)用, 也可以通過(guò) 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)用方;一個(gè)方法又可能會(huì)調(diào)用其它方法,形成一個(gè)調(diào)用鏈路的層次關(guān)系。

直接

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

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

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

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

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

鏈路

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

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

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

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

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

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

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

解決方案:

1.7.0 版本開(kāi)始(對(duì)應(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.     } 

然后我們?cè)賴L試觸發(fā)流控規(guī)則, 對(duì) /getStockDetail 進(jìn)行訪問(wèn),這里返回了FlowException

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

如果我們使用 OpenFeign 不添加 fallbackFactory 就會(huì)返回500 , 如果我們添加了就可以避免這個(gè)問(wèn)題。

  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 部分源碼:

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

流控效果

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

直接拒絕

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

Warm up

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

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

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

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

通過(guò) Jmeter 請(qǐng)求過(guò)后,可以看到如下效果,完成流控

勻速排隊(duì)

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

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

注意:勻速排隊(duì)模式暫時(shí)不支持 QPS > 1000 的場(chǎng)景。

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

然后我們通過(guò) jmeter 請(qǐng)求過(guò)后可以看到如下效果:

4. 降級(jí)規(guī)則

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

熔斷降級(jí)策略

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

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

我們可以在控制臺(tái)配置:

jmeter 模擬請(qǐng)求

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

我們可以在控制臺(tái)配置:

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

我們可以在控制臺(tái)配置:

熔斷降級(jí)說(shuō)明

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

 

Field

說(shuō)明

默認(rèn)值

resource

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

 

grade

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

慢調(diào)用比例

count

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

 

timeWindow

熔斷時(shí)長(zhǎng),單位為 s

 

minRequestAmount

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

5

statIntervalMs

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

1000 ms

slowRatioThreshold

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

5. 熱點(diǎn)規(guī)則

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

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

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

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

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

1. 首先資源必須是通過(guò) @SentinelResource 申明

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

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

注意:資源名稱要和 @SentinelResource 中的資源名稱對(duì)應(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)錯(cuò)誤 (限流熔斷業(yè)務(wù)邏輯)"); 
  18.     } 
  19.     //異常降級(jí)業(yè)務(wù)邏輯 
  20.     public static CommonResult<StockModel> fallback(@PathVariable Integer id) { 
  21.         return CommonResult.error(null, -100, "系統(tǒng)錯(cuò)誤 (異常降級(jí)業(yè)務(wù)邏輯)"); 
  22.     } 

返回異常信息:

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

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

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

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

  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ī)則不生效的問(wèn)題 
  15.         //com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser 
  16.         WebCallbackManager.setRequestOriginParser(new SentinelRequestOriginParser()); 
  17.         return registration; 
  18.     } 

規(guī)則配置

執(zhí)行請(qǐng)求

正常通過(guò)

異常不通過(guò)

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

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

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

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

  • Load 自適應(yīng)(僅對(duì) Linux/Unix-like 機(jī)器生效):系統(tǒng)的 load1 作為啟發(fā)指標(biāo),進(jìn)行自適應(yīng)系統(tǒng)保護(hù)。當(dāng)系統(tǒng) load1 超過(guò)設(shè)定的啟發(fā)值,且系統(tǒng)當(dāng)前的并發(fā)線程數(shù)超過(guò)估算的系統(tǒng)容量時(shí)才會(huì)觸發(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 使用率超過(guò)閾值即觸發(fā)系統(tǒng)保護(hù)(取值范圍 0.0-1.0),比較靈敏。
  • 平均 RT:當(dāng)單臺(tái)機(jī)器上所有入口流量的平均 RT 達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù),單位是毫秒。
  • 并發(fā)線程數(shù):當(dāng)單臺(tái)機(jī)器上所有入口流量的并發(fā)線程數(shù)達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)。
  • 入口 QPS:當(dāng)單臺(tái)機(jī)器上所有入口流量的 QPS 達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)。

原理

如下圖所示

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

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

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

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

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

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

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

配置頁(yè)面

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

8 集群流控

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

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

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

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

規(guī)則推送

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

這里先簡(jiǎn)單的介紹"原始模式"。

規(guī)則管理

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

規(guī)則推送

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

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

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

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

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

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

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

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

鑒權(quán)

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

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

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

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

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

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

參考文檔

 

https://github.com/alibaba/Sentinel/wiki/控制臺(tái)

 

責(zé)任編輯:武曉燕 來(lái)源: 運(yùn)維開(kāi)發(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 存儲(chǔ)Sentinel

2012-05-08 13:18:42

流控引擎流控

2021-05-21 08:30:26

Sentinel GateWay 微服務(wù)

2024-04-28 18:24:05

2022-05-29 21:38:11

限流熔斷流量

2011-03-23 10:13:09

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

2010-11-11 14:05:17

SQL Server排

2023-06-15 09:45:14

智能技術(shù)

2022-04-22 08:48:51

AQE流控架構(gòu)

2013-01-28 14:56:07

飛魚(yú)星無(wú)線路由器WLAN

2013-04-25 14:44:28

飛魚(yú)星無(wú)線路由器Wi-Fi

2021-03-23 15:50:53

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

2009-12-04 16:20:49

2013-02-19 14:09:40

點(diǎn)贊
收藏

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