Sentinel之流控規則


在上文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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM