Sentinel之流控規則

阿鑑發表於2021-12-13

在上文Sentinel流量防衛兵中講到了Sentinel入門以及流控規則一小部分,而Sentinel還有以下規則:

  • 熔斷降級規則
  • 熱點引數規則
  • 系統規則
  • 黑白名單規則

本文要講的是流控規則

流量控制規則

原理

監控應用流量的 QPS 或併發執行緒數等指標,當達到指定的閾值時對流量進行控制,以避免被瞬時的流量高峰沖垮,從而保障應用的高可用性。

QPS限流

這裡我們訪問一下/foo/test介面,觸發Sentinel控制檯初始化,就可以看到在簇點鏈路中重新整理出了該介面的資源

然後我們點選+流控新增流控規則,選擇QPS,並且限流為2

在高階選項中還有流控模式和流控效果兩個選擇,預設為直接和快速失敗,具體含義見下面解釋

新增之後,在頁面上快速點選幾次,就會看到我們之前預設好的限流提示

流控效果

流控效果只針對於QPS的流量控制

快速失敗

當QPS超過任意規則的閾值後,新的請求就會被立即拒絕,拒絕方式為丟擲FlowException。這種方式適用於對系統處理能力確切已知的情況下,比如通過壓測確定了系統的準確水位時。

案例見上

Warm Up

預熱/冷啟動方式,當系統長期處於低水位的情況下,當流量突然增加時,直接把系統拉昇到高水位可能瞬間把系統壓垮。通過"冷啟動",讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮。

在控制檯中刪除到剛剛測試的快速失敗規則,新增一個Warm up效果的規則

這裡我設定的qps閾值為10,預熱3秒,等效於想要達到10qps,需要預熱3秒。

這裡測試需要用到一些壓測工具,比如我用的是jmeter,畢竟在3秒內每秒連點10下我是做不到,認為自己行的可以自己試試。

以10qps進行壓測之後,可以實時監控中看到這麼一張效果圖

在左邊的線性圖中可以看到通過的qps(綠線)是在勻速上升狀態,直到3秒後達到10變為平穩狀態,具體的數值可以從右邊的表格看到。

排隊等待

排隊等待即為勻速排隊,該方式會嚴格控制請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應的是漏桶演算法。

同樣的,在控制檯新增規則

排隊等待的閾值最高只能配1000哦,至於為什麼小夥伴就自己想啦

以12qps進行壓測,檢視實時監控皮膚

qps一直保持在10, 規則生效了

流控模式

流控模式和呼叫關係有關,呼叫關係包括呼叫方、被呼叫方;一個方法又可能會呼叫其它方法,形成一個呼叫鏈路的層次關係。

直接

根據呼叫來源進行限流,預設為default,即針對所有的來源,這裡面還可以配置自定義的來源。

1.自定義來源

自定義來源需要修改我們的配置程式碼,更改方式如下

private void addSpringMvcInterceptor(InterceptorRegistry registry) {
  SentinelWebMvcConfig config = new SentinelWebMvcConfig();

  config.setBlockExceptionHandler(new MyBlockExceptionHandler());
  // 區分請求方式
  config.setHttpMethodSpecify(true);
  // 請求來源解析
  config.setOriginParser(request -> request.getHeader("User-Agent"));
  registry.addInterceptor(new SentinelWebInterceptor(config)).addPathPatterns("/**");
}

在原來的配置中增加來源解析的配置,比如我這裡就是獲取請求頭中的User-Agent作為請求來源,你也可以根據自己的需求決定,比如獲取客戶端的ip

修改完畢後,重啟服務,在控制檯新增一個來源為test的規則

然後在請求上加上User-Agent的header,測試

這裡如果把User-Agent換成其他的,則不會被限流

2. 其他

其他的意思除了指定的來源都會被限流,看到這裡的就會讓人有所疑問

  • 控制檯增加了other來源的配置,之前的test來源就不會限流了嗎?

其實它的意思是這樣的:除了test來源的請求,其他來源的qps都不能超過其他這條配置,舉個例子

test來源限流的qps為2,other來源限流的qps為1,那麼此時如果是來自test2來源的請求,qps超過1則會提示已被限流,test來源的請求仍舊是超過2之後才會提示被限流。

在控制檯增加一條其他來源的配置

設定User-Agenttest2進行測試

可以看到,我這裡只請求了1次就被限流了

關聯

關聯這個模式指的是如果一個資源被兩個介面所訪問,那麼在一個介面超過qps閾值時,可以對另一個介面進行限流。

舉個例子來說,FooService同時被A介面和B介面所訪問,由於FooService總體能夠接受的qps是恆定的,如果A介面qps過高,那麼B介面的就會受到影響,如果我們想要B介面優先,此時我們就可以配置一條當B介面超過qps閾值時,就把A介面限流。

聽起來是不是特別彆扭?, 如果這倆介面有思考能力,我自行腦補出了以下場景:

B介面:我超速了,警察,快把A介面逮捕了,它影響到我超速了。

A介面:???

在程式碼裡面新增一個foo/test2介面,重啟服務

在控制檯增加配置

以上配置表示:當/foo/test介面達到qps為10的閾值時,就對/foo/test2進行限流

測試方式:使用jmeter對/foo/test介面進行壓測,然後再請求/foo/test2看看是否被限流了

假裝已經開始對/foo/test介面進行壓測了,請求/foo/test2

可以看到,這裡隨便請求了一下就返回了限流提示

鏈路

鏈路模式和關聯模式有點像,但是不再是我影響你這種關係了。而指的是如果一個資源被兩個介面所訪問,那麼我們可以指定只對其中某個介面進行限流。

還是那個例子,FooService同時被A介面和B介面所訪問,此時如果想對UserService作qps為10的限流,之前的方式就是直接配置一個FooServiceqps閾值為10的規則,這樣A,B兩個介面都會被限制訪問,但是如果我只想對A介面的訪問進行限流,B介面的不管,那麼就需要使用鏈路模式了。

但是但是,在目前最新的版本(1.8.2)裡,這個規則不生效!

併發執行緒數

概念

不同於qps,併發執行緒數限定的是某個資源的執行緒數併發上線,用於保護業務執行緒池不被慢呼叫耗盡。

前段時間我的同事就剛好遇上了這樣的問題:

某個介面因為一個bug,執行緒被阻塞了, 導致所有打到這個介面的請求全部陷入阻塞狀態。我們知道tomcat的匯流排程數是有限的,出現這個問題之後的一小會,這個服務的所有執行緒都阻塞在這個介面上了,tomcat執行緒池直接耗盡,所有介面502

如果當時該介面的併發數存在一個閾值,那這個bug所涉及的範圍就可以控制在很小的範圍內了。

演示

新增一個介面,用於模擬執行緒併發情況

public String test3() throws InterruptedException {
  // 執行緒停頓1秒,
  TimeUnit.SECONDS.sleep(1);
  return "ok";
}

重啟服務,訪問/foo/test3介面觸發初始化

在控制檯新增配置

開啟jmeter進行壓測該介面,然後在其他地方訪問一下(為了好觀察)

規則生效了。

其他的流控模式與qps方式相同,這裡就不演示了

小結

本文介紹了Sentinel的流控規則,其中根據場景分為QPS限流以及併發執行緒數限流。

這兩個限流策略的共同點為:可以對來源進行鍼對限流,支援直接,關聯,鏈路三種流控模式。

QPS限流還包含了三種流控效果: 快速失敗、預熱、排隊等待。

至於是否叢集那個選項小夥伴就當沒看到哈,我搞不定這個,我認慫

實在想研究,官方文件在此:https://github.com/alibaba/Sentinel/wiki/叢集流控

本文案例程式碼:https://gitee.com/lzj960515/my-micro-service-demo

追更,想要了解更多精彩內容,歡迎關注公眾號:程式設計師阿鑑

個人部落格空間:https://zijiancode.cn

相關文章