轉載聲明 : 該文章出處為 扛麻袋的少年
本文目錄:
-
- 寫在開頭
- 1.流控規則
-
- 1.1 門檻值類型:QPS
- 1.2 門檻值類型:線程數
- 1.3 流控模式:直接
- 1.4 流控模式:關聯
- 1.5 流控模式:鍊路
- 1.6 流控效果:快速失敗
- 1.7 流控效果:Warm Up
- 1.8 流控效果:排隊等待
- 2.降級規則
-
- 2.1 RT
- 2.2 異常比例
- 2.3 異常數
- 3.熱點規則
-
- 3.1 何為熱點
- 3.2 何為熱點限流
- 3.3 熱點規則
-
- Ⅰ.基本配置
- Ⅱ.參數例外項配置
- 4.系統規則
-
- 1.系統規則支援以下模式
- 2. 入口QPS配置
寫在開頭
接上一篇文章:Spring Cloud Alibaba Sentinel 介紹、簡單使用。學習了Sentinel 的基本使用,接下來我們就對 Sentine 中的
那些規則
進行一一介紹,本文重點講以下4個。

1.流控規則
流控規則,即:流量控制規則。可自行參考官網介紹:GitHub 流量控制。具體配置有
資源名
、
針對來源
、
門檻值類型
、
是否叢集
、
流控模式
、
單機門檻值
、
流控效果
這幾項,它們配合進行使用。每一項具體代表的什麼含義,且聽我娓娓道來。
資源名
:唯一路徑,預設為請求路徑(也可以是後續介紹的 @SentinelResource 注解的 value 屬性值)
針對來源
:Sentinel 可以針對調用者進行限流,填寫微服務名。預設為 default(不區分來源)
:本文為單機測試,是否叢集不選
是否叢集
1.1 門檻值類型:QPS
QPS(每秒鐘的請求數量):當調用該 API 的
QPS
達到門檻值的時候,進行限流。
配置:
配置說明:
/testA 服務,每秒隻允許調用 1 次,超出門檻值後,流控效果為:
直接 → 快速失敗
(流控效果如果不選,預設為
直接 → 快速失敗
)。
資源名稱 | 門檻值類型 | 單機門檻值 | 流控模式 | 流控效果 |
---|---|---|---|---|
/testA | | 1 | 直接 | 快速失敗 |
業務代碼:
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA() throws InterruptedException {
return "-----testA";
}
}
測試:
開始,每秒調用 /testA 服務 1次,服務正常。後續狂點重新整理調用服務,顯然超過 Sentinel 設定的 QPS = 1,就會進行流量控制:
快速失敗
(流控 Sentinel 預設提示:
Blocked by Sentinel(flow limiting)
)
1.2 門檻值類型:線程數
線程數:當調用該 API 的
線程數
達到門檻值的時候,進行限流。
配置:
配置說明:
/testA 服務,單個線程隻允許調用 2 次,超出門檻值後,流控效果為:
直接 → 快速失敗
。
資源名稱 | 門檻值類型 | 單機門檻值 | 流控模式 | 流控效果 |
---|---|---|---|---|
/testA | | | 直接 | 快速失敗 |
業務代碼:
/**
* 使/testA休眠6s
*/
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(6000);
return "-----testA";
}
}
測試:
開始,調用 /testA 服務 2 次,服務正常,但是 sleep 導緻服務沒有傳回。當第 3 次調用時,顯然超過 Sentinel 設定的 線程數 = 2,就會進行流量控制:
快速失敗
(本次以 Firefox 進行測試,Chrome 是多線程執行??總是出不來效果,和浏覽器設計有關系吧,此處就不過多考慮)
1.3 流控模式:直接
流控模式:直接,已經介紹,字面了解即可。沒啥可說的。
這些選項都是配合使用的,了解意思即可
1.4 流控模式:關聯
關聯:當關聯的資源達到門檻值時,就限流自己。
當與 A 資源關聯的 B 資源達到門檻值時,就限流自己(A)
,即:B惹事,A挂了
應用場景:
雙十一,
支付接口
和
下單接口
關聯。當支付接口達到門檻值,就限流下單接口
配置:
配置說明:
/testA
服務關聯
/testB
服務,1s 調用 1次,服務正常。當狂點重新整理調用
/testB
服務,超出門檻值 QPS = 1 後,此時 /testA 被限流了,這就是
B惹事,A挂了
。
資源名稱 | 門檻值類型 | 單機門檻值 | 流控模式 | 關聯資源 | 流控效果 |
---|---|---|---|---|---|
/testA | | | 關聯 | | 快速失敗 |
業務代碼:
/**
* 使/testA休眠6s
*/
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
return "-----testA";
}
@GetMapping("/testB")
public String testB(){
return "-----testB";
}
}
測試:
開始,/testA 和 /testB 1次/s 可以正常調用,突然大批量通路打到 /testB 請求。由于關聯的 /testB 請求超過設定的門檻值 QPS = 1,導緻 /testA 請求被限流了。
1.5 流控模式:鍊路
鍊路:當鍊路中的資源達到門檻值時,就會對使用到該資源的鍊路進行流控。
當 A01 資源達到設定門檻值時,所有調用該服務的鍊路,都會被限流
,即:
A01 挂了,用到我的鍊路都得挂
此處會用到
@SentinelResource
注解 value 屬性值
作為資源名
。此處隻是使用一下。該注解的詳細使用,請跳轉連結:@SentinelResource 介紹
模拟兩條請求鍊路:
- A鍊路:
A → A01 → A04 → A05
- B鍊路:
B → A01 → A02 → A03
Spring Cloud Alibaba Sentinel 流控、降級、熱點、系統規則詳解
配置:
配置說明:
對
testA01
服務進行
鍊路
流控,該服務關聯有 A 和 B 兩條鍊路。當 A 鍊路1s 調用 1次,服務正常。當該鍊路調用
超出門檻值 QPS = 1 後,此時A鍊路都會被限流,同時因為B鍊路也調用 testA01,是以B鍊路也會同時被限流調用
。
資源名稱 | 針對來源 | 門檻值類型 | 單機門檻值 | 流控模式 | 入口資源 | 流控效果 |
---|---|---|---|---|---|---|
| default | | | 鍊路 | | 快速失敗 |
業務代碼:
/**
* Controller代碼
*/
@RestController
@Slf4j
public class FlowLimitController {
@Resource(name = "commonService")
public CommonService commonService;
@GetMapping("/testA")
@SentinelResource("testA")
public String testA(){
commonService.testA01();
return "-----testA";
}
@GetMapping("/testB")
@SentinelResource("testB")
public String testB(){
commonService.testA01();
return "-----testB";
}
}
/**
* Service代碼
*/
@Service("commonService")
@Slf4j
public class CommonService {
@SentinelResource(value = "testA01")
public void testA01() {
testA02();
testA04();
log.info("-----testA01");
}
@SentinelResource(value = "testA02")
public void testA02() {
testA03();
log.info("-----testA02");
}
@SentinelResource(value = "testA03")
public void testA03() {
log.info("-----testA03");
}
@SentinelResource(value = "testA04")
public void testA04() {
testA05();
log.info("-----testA04");
}
@SentinelResource(value = "testA05")
public void testA05() {
log.info("-----testA05");
}
}
測試:
開始,對
/testA 請求
1次/s 可以正常調用,當
/testA 請求
QPS > 1 後,滿足設定的
testA01鍊路流控
規則 ,是以
/testA 請求
會被限流。同時
/testB 請求
也會被限流。 (即:testA01 QPS=1,1s 隻允許調用1次,超出之後,調用 testA01 的所有鍊路将都會被限流)
手速原因,此處使用 postman 1s 發送 10個請求(/testA 和 /testB 各10個),測試圖如下所示:
1.6 流控效果:快速失敗
流控效果:快速失敗,已經介紹,字面了解即可。沒啥可說的。
這些選項都是配合使用的,了解意思即可
1.7 流控效果:Warm Up
Warm Up:某個服務,日常通路量很少,基本為 0,突然1s通路量 10w,這種極端情況,會直接将服務擊垮。是以通過配置
流控效果:Warm Up
,允許系統慢慢呼呼的進行預熱,經預熱時長逐漸升至設定的QPS門檻值。
公式計算:
公式:門檻值/coldFactor(預設值為3)
應用場景:
秒殺系統。秒殺系統在開啟的瞬間,會有很多的流量上來,很有可能将系統打死。預熱方式就是為了保護系統,可以慢慢的将流量放進來,最終将門檻值增長到指定的數值
配置:
配置說明:
/testA
服務,設定 QPS 單機門檻值為 10,采用 Warm Up 預熱的方式,預熱時長為 5s。根據計算公式
10 / 3 = 3
,前 5s 的門檻值為 3,預熱 5s 後門檻值增長到 10。
資源名稱 | 門檻值類型 | 單機門檻值 | 流控模式 | 流控效果 | 預熱時長 |
---|---|---|---|---|---|
/testA | | | 直接 | | |
業務代碼:
/**
* 使/testA休眠6s
*/
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
return "-----testA";
}
@GetMapping("/testB")
public String testB(){
return "-----testB";
}
}
測試:
開始調用 /testA 服務,狂點重新整理通路打到 /testA 請求。配置
Warm Up
流控效果,在前 5s 内,通過公式計算門檻值為
10/3 = 3
,通路超過 3 次便會被限流;5s 後,門檻值增長到 10,此時通路超過 3 次也不會被限流,這就是 Warm Up 預熱效果。
1.8 流控效果:排隊等待
排隊等待:讓請求以均勻的速度通過,對應的是漏桶算法。這種方式主要用于處理間隔性突發的流量,例如消息隊列。
應用場景:
在某一秒有大亮的請求到來,而接下來的幾秒則處于空閑狀态。我們希望系統能夠在接下來的空閑期間逐漸處理這些請求,而不是在第一秒直接拒絕多餘的請求。
配置:
配置說明:
/testA
服務,設定 QPS 單機門檻值為 2,每秒隻接收 2 個請求。設定逾時時間 5s。采用漏鬥算法,讓背景勻速的處理請求,而不是直接拒絕更多的請求。逾時的請求則被抛棄,傳回錯誤資訊。
資源名稱 | 門檻值類型 | 單機門檻值 | 流控模式 | 流控效果 | 預熱時長 |
---|---|---|---|---|---|
/testA | | | 直接 | | |
業務代碼:
/**
* 使/testA休眠6s
*/
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
return "-----testA";
}
}
測試:
手速不夠,此處就使用 postman 一次發送 100 個請求,設定 QPS = 2,其他請求将會排隊等待。每秒隻接收 2 個請求。我們會看到動态監控,
通過QPS為 2,拒絕QPS 為 0,平均響應時間為 480ms,我們設定逾時時間為 5000ms,是以拒絕QPS 為 0,如果逾時時間為 200ms,拒絕 QPS 就會上升。100個請求發送完成,随之通過QPS降下來了。
postman 一次如何發送多個請求,參考:postman 點選一次連續發送多個請求
2.降級規則
降級規則。可自行參考官網介紹:GitHub 熔斷降級。降級政策有
RT
、
異常比例
、
異常數
三種,每一項具體代表的什麼含義,繼續聽我娓娓道來。
資源名
:唯一路徑,預設為請求路徑(也可以是後續介紹的 @SentinelResource 注解的 value 屬性值)
2.1 RT
RT:即
平均響應時間(DEGRADE_GRADE_RT)
。官網介紹太籠統,此處不Copy 了,要看官網介紹來這裡:RT 平均響應時間介紹
注意 Sentinel 預設統計的 RT 上限是 4900 ms,超出此門檻值的都會算作 4900 ms,若需要變更此上限可以通過啟動配置項 -Dcsp.sentinel.statistic.max.rt=xxx 來配置。
圖示:
配置:
配置說明:
/testA
服務,設定 降級政策為
RT
,RT(平均響應時間)為
200ms
,時間視窗為
5s
。發送請求平均響應時間在 200ms 内,正常通路不會被熔斷降級。當平均響應時間 > 200ms,便會被熔斷降級。
時間視窗5s内斷路器處于打開狀态,無法提供服務,時間視窗結束,服務恢複正常通路。就是服務會被熔斷5s的意思
(切記是平均響應時間)
資源名稱 | 降級政策 | RT(平均響應時間) | 時間視窗 |
---|---|---|---|
/testA | | | |
業務代碼:
/**
* 使/testA休眠300ms
*/
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(300);
return "-----testA";
}
}
測試:
RT降級規則,需要同時滿足:
1.QPS>=5
&&
2.平均響應時長> 200
兩個條件。手動發送請求操作看的明顯,此時 1秒鐘發送 >5 個請求,由于每個請求都 sleep 300ms,請求最終平均響應時間為 300+ ms,肯定 > 200ms。
滿足上述兩個條件,執行 RT 降級規則,開始熔斷後,時間視窗期5s内,斷路器處于打開狀态,此時為熔斷階段,時間視窗結束,斷路器關閉,關閉服務熔斷,服務可以正常通路。
如圖所示:
2.2 異常比例
異常比例:
QPS >= 5
&&
異常比例超過設定的門檻值
,便會發生服務降級 。
異常比例為 0.0~1.0 範圍内值。
時間視窗就是斷路器開啟時間長短(降級時間)
。要看官網介紹來這裡:異常比例介紹
圖示:
配置:
配置說明:
/testA
服務,設定 降級政策為
異常比例
,異常比例設為
0.5
,時間視窗為
5s
。即:1s 發送6個請求,異常比例超過 50%,就會被熔斷,斷路器打開5s,5s後自動關閉,繼續提供服務。
資源名稱 | 降級政策 | 異常比例(0.0-1.0) | 時間視窗 |
---|---|---|---|
/testA | | | |
業務代碼:
/**
* 自己造一個 by zero 異常
*/
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
int i = 10/0;
return "-----testA";
}
}
測試:
我們配置的異常比例降級規則,需要同時滿足:
1.QPS>=5
&&
2.異常比例> 50%
兩個條件。手動發送請求操作看的明顯,此時 1秒鐘發送 >5 個請求,因為每個請求都是異常,異常比例 100%。
如果1s發送6次請求,前3次報錯,因為第4次通路後,異常比例 > 50%,第4次便會被熔斷,報
Blocked by Sentinel(flow limiting)
。5s後繼續提供服務哦。測試結果如圖所示:
2.3 異常數
異常數:指的是資源
近1分鐘
的異常數目,超過門檻值之後會進行熔斷。
重點注意:異常數,統計時間視窗是分鐘級别,若 timeWindow 小于 60s,則結束熔斷狀态後仍可能再次進入熔斷狀态。推薦
時間視窗一定要>=60s
官網介紹來這裡看:異常數介紹
圖示:
配置:
配置說明:
/testA
服務,設定 降級政策為
異常數
,異常數設為
5
,時間視窗為
60s
。即:調用服務,當異常數超過5個時,開啟斷路器,執行熔斷操作。60s 後,斷路器關閉,服務恢複正常,如下圖:
資源名稱 | 降級政策 | 異常數 | 時間視窗 |
---|---|---|---|
/testA | | | |
業務代碼:
/**
* 自己造一個 by zero 異常
*/
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
int i = 10/0;
return "-----testA";
}
}
測試:
執行 /testA 服務請求,因為每個請求都是異常,前5次調用正常傳回,隻是報異常到前台;第6次服務調用時,便會被降級熔斷。報
Blocked by Sentinel(flow limiting)
。60s後繼續提供服務哦。測試結果如圖所示:
3.熱點規則
3.1 何為熱點
(本段内容摘自:Github 熱點規則官方介紹)
何為熱點?熱點即經常通路的資料。很多時候我們希望統計某個熱點資料中通路頻次最高的 Top K 資料,并對其通路進行限制。比如:
商品 ID 為參數,統計一段時間内最常購買的商品 ID 并進行限制
使用者 ID 為參數,針對一段時間内頻繁通路的使用者 ID 進行限制
熱點參數限流會統計傳入參數中的熱點參數,并根據配置的限流門檻值與模式,對包含熱點參數的資源調用進行限流。
熱點參數限流可以看做是一種特殊的流量控制,僅對包含熱點參數的資源調用生效。
Sentinel 利用 LRU 政策統計最近最常通路的熱點參數,結合令牌桶算法來進行參數級别的流控。熱點參數限流支援叢集模式。(詳細介紹,參考:Github 熱點規則官方介紹)
3.2 何為熱點限流
一句話解釋:根據 url 傳遞進來的參數進行限流。帶這個參數就限流,不帶就不限流。
3.3 熱點規則
熱點規則。可自行參考官網介紹:GitHub 熱點參數限流,共有
資源名
、
限流模式(隻支援QPS模式)
、
參數索引
、
單機門檻值
、
統計視窗時長
、
是否叢集
六種參數;進階選項還有額外一些參數,在用到時介紹。每一項具體代表的什麼含義,來繼續聽我絮絮叨叨吧。
此處會用到
@SentinelResource
注解 value 屬性值
作為資源名
。此處隻是使用一下。該注解的詳細使用,請跳轉連結:@SentinelResource 介紹
:唯一路徑,預設為請求路徑。此處必須是 @SentinelResource 注解的 value 屬性值,配置@GetMapping 的請求路徑無效)
資源名
:參數索引(從0開始,0表示第一個參數、1表示第二個參數)
參數索引
Ⅰ.基本配置
[email protected] 注解說明
@SentinelResource 注解,與 @HystrixCommand 類似,也是用來定義服務降級
兜底方法
的注解。該注解有很多屬性可以配置。在下一篇會系統介紹:@SentinelResource 介紹
2.業務代碼:
@RestController
public class FlowLimitController {
@GetMapping("/testC")
@SentinelResource(value = "testC") //此處value值,一般為@GetMapping屬性值去掉斜杠
public String testC(@RequestParam(value = "id",required = false) Integer id,
@RequestParam(value = "name",required = false) String name){
return "-----testC";
}
}
3.配置:
4.配置說明:
對
/testC
服務,配置熱點key限流。當 1.參數 name 存在 2.一秒内調用
/testC
服務 > 5次,滿足限流規則。服務将被熔斷。斷路器打開,5s 後服務恢複正常
資源名稱 | 參數索引 | 單機門檻值 | 統計視窗時長 |
---|---|---|---|
(不能是請求路徑,否則無效) | | | |
5.測試:
調用 URL:
http://localhost:8401/testC?id=1&name=James
,1.參數 name 存在 2.一秒内調用
/testC
服務 > 5次,滿足限流規則。服務将被熔斷。斷路器打開,5s 後服務恢複正常。如下圖:
6.友好處理
被限流後,直接報錯
java.lang.refletc.UndeclaredThrowableException
。異常顯示到前台使用者界面,顯然不是不友好。
此處也是需要用到 @SentinelResource 的 blockHandler 屬性,它是 Sentinel控制台違規的兜底方法配置(還會j介紹一個 fallback屬性,它是@GetMapping請求Java 方法執行出現異常的兜底方法配置,要厘清楚)
兜底方法配置,在下一篇介紹:@SentinelResource 介紹
Ⅱ.參數例外項配置
1.需求:
當 name 參數值為
Wade
時,限流門檻值變更為 100。此時就需要對
參數例外項
進行配置了。
參數類型
支援:
int
、
double
、
String
、
long
、
float
、
char
、
byte
7種類型,
參數值
指 name 參數的值,
限流門檻值
指該參數值允許的門檻值。
2.配置:
3.測試:
調用 URL:
http://localhost:8401/testC?id=1&name=Wade
,雖然 name 參數存在,但是配置了 Wade 限流門檻值為 100。我手速沒那麼快,哈哈,是以不會進入熔斷。如下圖所示:
4.系統規則
系統保護規則是從應用級别的入口流量進行控制
,從單台機器的 load、CPU 使用率、平均 RT、入口 QPS 和并發線程數等幾個次元監控應用名額,讓系統盡可能跑在最大吞吐量的同時保證系統整體的穩定性。
系統保護規則是應用整體次元的,而不是資源次元的,并且僅對入口流量生效。入口流量指的是進入應用的流量(EntryType.IN),比如 Web 服務或 Dubbo 服務端接收的請求,都屬于入口流量。
Sentinel 系統自适應限流從整體次元對應用入口流量進行控制
,結合應用的 Load、CPU 使用率、總體平均 RT、入口 QPS 和并發線程數等幾個次元的監控名額,通過自适應的流控政策,讓系統的入口流量和系統的負載達到一個平衡,讓系統盡可能跑在最大吞吐量的同時保證系統整體的穩定性。
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 達到門檻值即觸發系統保護。
此處内容,
CPU 使用率
、
總平均 RT
、
并發線程數
等也不好示範,了解意思知道有這塊用于全局應用入口流量控制就可以了,詳細介紹還是參考官網來吧:熱點參數限流
2. 入口QPS配置
入口QPS,實用性還是比較危險的。 如果 sentinel 密碼被修改,将你的整個系統
入口QPS
配置很小,那麼整個系統就癱瘓了。
但是 入口QPS 有總控的功能。最終選擇是否使用,還是視情況而定吧
配置:
配置說明:
整個系統,每個請求 QPS = 1 正常通路,當該請求 QPS >1 就會被限流。
測試:
本文代碼不提供,将文中業務代碼配合如下代碼使用即可。下載下傳位址:Spring Cloud Alibaba Sentinel 簡單使用 (提取碼:nfmb)
下一篇:來聊聊@SentinelResource的用法