Springcloud-Alibaba 〖十五〗Sentinel 熱點參數限流 系統規則 SentinelResource配置
一. 熱點參數限流
何爲熱點?熱點即經常訪問的數據。很多時候我們希望統計某個熱點數據中訪問頻次最高的 Top K 數據,並對其訪問進行限制。比如:
- 商品 ID 爲參數,統計一段時間內最常購買的商品 ID 並進行限制
- 用戶 ID 爲參數,針對一段時間內頻繁訪問的用戶 ID 進行限制
熱點參數限流會統計傳入參數中的熱點參數,並根據配置的限流閾值與模式,對包含熱點參數的資源調用進行限流。熱點參數限流可以看做是一種特殊的流量控制,僅對包含熱點參數的資源調用生效。
二. 熱點規則配置
2.1 8401項目新增方法
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHostkey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
@RequestParam(value = "p2",required = false) String p2) {
return "-----testHotKey";
}
public String deal_testHostkey(String p1, String p2, BlockException e){
return "-----deal_testHotKey";
}
- SentinelResource註解的 value 表示註冊到Sentinel的資源名稱
- blockHandler 默認的兜底規則,表示出錯了會返回我們自己寫的方法中,其中我們自己寫的方法中要增加一個BlockException 參數
2.2 Sentinel配置熱點規則
當我們第一個參數訪問次數大於1QPS我們會拋出我們自己的兜底方法
2.3 測試
當我們不超過規則時
當觸發熱點規則時(攜帶的參數爲p1時),會返回我們自己定義的兜底方法,看起來是不是非常克萊彎呢~
但是我們沒有攜帶指定參數p1時可以隨便訪問
2.4 熱點規則高級配置
我們期望p1參數當它是某個特殊值時,它的限流值和平時不一樣
就是充錢了~我VIP不得是人上人嗎?(暗示自己)
測試,我們把參數設置爲5隨便點都不會限流(QPS<=200)
PS小貼士~
三. 系統規則
官網複製機~~
Sentinel 系統自適應限流從整體維度對應用入口流量進行控制,結合應用的 Load、CPU 使用率、總體平均 RT、入口 QPS 和併發線程數等幾個維度的監控指標,通過自適應的流控策略,讓系統的入口流量和系統的負載達到一個平衡,讓系統儘可能跑在最大吞吐量的同時保證系統整體的穩定性。
3.1 參數列表
系統規則支持以下的模式:
- **Load 自適應(**僅對 Linux/Unix-like 機器生效):系統的 load1 作爲啓發指標,進行自適應系統保護。當系統 load1 超過設定的啓發值,且系統當前的併發線程數超過估算的系統容量時纔會觸發系統保護(BBR 階段)。系統容量由系統的 maxQps * minRt 估算得出。設定參考值一般是 CPU cores * 2.5。
- CPU usage(1.5.0+ 版本):當系統 CPU 使用率超過閾值即觸發系統保護(取值範圍 0.0-1.0),比較靈敏。
- 平均 RT:當單臺機器上所有入口流量的平均 RT 達到閾值即觸發系統保護,單位是毫秒。
- 併發線程數:當單臺機器上所有入口流量的併發線程數達到閾值即觸發系統保護。
- 入口 QPS:當單臺機器上所有入口流量的 QPS 達到閾值即觸發系統保護。
四. SentinelResource配置
4.1 8401項目新增依賴
這個是之前的公共類
<dependency>
<groupId>com.aiguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
4.2 新增Controller RateLimitController
package com.atguigu.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RateLimitController {
@GetMapping("/byResource" )
@SentinelResource(value = "byResource" , blockHandler = "handleException")
public CommonResult byResource(){
return new CommonResult( 200, "按資源名稱限流測試oK" ,new Payment( 2020L, "serial001"));
}
public CommonResult handleException(BlockException exception){
return new CommonResult( 444, exception.getClass().getCanonicalName()+"\t 服務不可用");
}
}
4.3 新增限流規則
4.4 測試
但是服務重啓後,規則就消失了,所以這個是一個臨時規則
4.5 新增Url方法
Controller層新增Url方法
@GetMapping("/rateLimit/byUrl" )
@SentinelResource(value = "byUr1")
public CommonResult byUrl(){
return new CommonResult( 200, "按ur1限流測試oK",new Payment( 2020L, "seria1002"));
}
沒配置的時候是默認的規則方法
4.6 出現的問題
4.7 全局的兜底方法
controller新增方法
@GetMapping("/rateLimit/customerBlockHandler" )
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class,blockHandler="handlerException2")
public CommonResult customerBlockHandler(){
return new CommonResult( 200, "按客戶自定義",new Payment( 2020L, "seria1003"));
}
新增全局兜底類(注意方法必須是static的)
package com.atguigu.springcloud.handler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
public class CustomerBlockHandler {
public static CommonResult handlerException(BlockException e){
return new CommonResult( 444, "按客戶自定義,global handlerException-------1 ");
}
public static CommonResult handlerException2(BlockException e){
return new CommonResult( 444, "按客戶自定義,global handlerException-------2 ");
}
}
這裏我們要切記
測試