0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Sentinel為什么這么強(qiáng),我扒了扒背后的實(shí)現(xiàn)原理

jf_ro2CN3Fa ? 來源:三友的java日記 ? 2023-05-05 09:32 ? 次閱讀


最近我在整理代碼倉庫的時(shí)候突然發(fā)現(xiàn)了被塵封了接近兩年之久的Sentinel源碼庫

兩年前我出于好奇心扒了一下Sentinel的源碼,但是由于Sentinel本身源碼并不復(fù)雜,在簡單扒了扒之后幾乎就再?zèng)]扒過了

那么既然現(xiàn)在又讓我看到了,所以我準(zhǔn)備再來好好地扒一扒,然后順帶寫篇文章來總結(jié)一下。

Sentinel簡介

Sentinel是阿里開源的一款面向分布式、多語言異構(gòu)化服務(wù)架構(gòu)的流量治理組件。

主要以流量為切入點(diǎn),從流量路由、流量控制、流量整形、熔斷降級、系統(tǒng)自適應(yīng)過載保護(hù)、熱點(diǎn)流量防護(hù)等多個(gè)維度來幫助開發(fā)者保障微服務(wù)的穩(wěn)定性。

上面兩句話來自Sentinel官網(wǎng)的自我介紹,從這短短的兩句話就可以看出Sentinel的定位和擁有的強(qiáng)大功能。

基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

  • 項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 視頻教程:https://doc.iocoder.cn/video/

核心概念

要想理解一個(gè)新的技術(shù),那么首先你得理解它的一些核心概念

資源

資源是Sentinel中一個(gè)非常重要的概念,資源就是Sentinel所保護(hù)的對象。

資源可以是一段代碼,又或者是一個(gè)接口,Sentinel中并沒有什么強(qiáng)制規(guī)定,但是實(shí)際項(xiàng)目中一般以一個(gè)接口為一個(gè)資源,比如說一個(gè)http接口,又或者是rpc接口,它們就是資源,可以被保護(hù)。

資源是通過Sentinel的API定義的,每個(gè)資源都有一個(gè)對應(yīng)的名稱,比如對于一個(gè)http接口資源來說,Sentinel默認(rèn)的資源名稱就是請求路徑。

規(guī)則

規(guī)則也是一個(gè)重要的概念,規(guī)則其實(shí)比較好理解,比如說要對一個(gè)資源進(jìn)行限流,那么限流的條件就是規(guī)則,后面在限流的時(shí)候會(huì)基于這個(gè)規(guī)則來判定是否需要限流。

Sentinel的規(guī)則分為流量控制規(guī)則、熔斷降級規(guī)則以及系統(tǒng)保護(hù)規(guī)則,不同的規(guī)則實(shí)現(xiàn)的效果不一樣。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

  • 項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn/video/

來個(gè)Demo

為了兼顧文章的完整性和我一貫的風(fēng)格,必須要來個(gè)demo,如果你已經(jīng)使用過了Sentinel,那么就可以直接pass這一節(jié),直接快進(jìn)到核心原理。

1、基本使用

引入依賴

<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-coreartifactId>
<version>1.8.6version>
dependency>

測試代碼

publicclassSentinelSimpleDemo{

publicstaticvoidmain(String[]args){
//加載流控規(guī)則
initFlowRules();

for(inti=0;i5;i++){
Entryentry=null;
try{
entry=SphU.entry("sayHello");
//被保護(hù)的邏輯
System.out.println("訪問sayHello資源");
}catch(BlockExceptionex){
System.out.println("被流量控制了,可以進(jìn)行降級處理");
}finally{
if(entry!=null){
entry.exit();
}
}
}
}

privatestaticvoidinitFlowRules(){
Listrules=newArrayList<>();

//創(chuàng)建一個(gè)流控規(guī)則
FlowRulerule=newFlowRule();
//對sayHello這個(gè)資源限流
rule.setResource("sayHello");
//基于qps限流
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//qps最大為2,超過2就要被限流
rule.setCount(2);

rules.add(rule);

//設(shè)置規(guī)則
FlowRuleManager.loadRules(rules);
}

}

解釋一下上面這段代碼的意思

  • initFlowRules方法就是加載一個(gè)限流的規(guī)則,這個(gè)規(guī)則作用于sayHello這個(gè)資源,基于qps限流,當(dāng)qps超過2之后就會(huì)觸發(fā)限流。
  • SphU.entry("sayHello")這行代碼是Sentinel最最核心的源碼,這行代碼表面看似風(fēng)平浪靜,實(shí)則暗流涌動(dòng)。這行代碼表明接下來需要訪問某個(gè)資源(參數(shù)就是資源名稱),會(huì)去檢查需要被訪問的資源是否達(dá)到設(shè)置的流控、熔斷等規(guī)則。對于demo來說,就是檢查sayHello這個(gè)資源是否達(dá)到了設(shè)置的流量控制規(guī)則。
  • catch BlockException也很重要,當(dāng)拋出BlockException這個(gè)異常,說明觸發(fā)了一些設(shè)置的保護(hù)規(guī)則,比如限流了,這里面就可以進(jìn)行降級操作。
  • System.out.println("訪問sayHello資源")這行代碼表面是一個(gè)打印語句,實(shí)則就是前面一直在說的需要被保護(hù)的資源。

所以上面這段代碼的整體意思就是對sayHello這個(gè)需要訪問的資源設(shè)置了一個(gè)流控規(guī)則,規(guī)則的內(nèi)容是當(dāng)qps到達(dá)2的時(shí)候觸發(fā)限流,之后循環(huán)5次訪問sayHello這個(gè)資源,在訪問之前通過SphU.entry("sayHello")這行代碼進(jìn)行限流規(guī)則的檢查,如果達(dá)到了限流的規(guī)則的條件,會(huì)拋出BlockException。

測試結(jié)果

55d9aab0-eadc-11ed-90ce-dac502259ad0.png

從結(jié)果可以看出,當(dāng)前兩次訪問sayHello成功之后,qps達(dá)到了2,之后再訪問就被限流了,失敗了。

2、集成Spring

在實(shí)際的項(xiàng)目使用中一般不會(huì)直接寫上面的那段demo代碼,而是集成到Spring環(huán)境底下。

引入依賴

<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<version>2.2.5.RELEASEversion>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
<version>2.2.5.RELEASEversion>
dependency>

之后提供一個(gè)/sayHello接口

@RestController
publicclassSentinelDemoController{

@GetMapping("/sayHello")
publicStringsayHello()throwsInterruptedException{
return"hello";
}

}

配置文件

server:
port:9527

spring:
application:
name:SentinelDemo

到這demo就搭建完成了。

此時(shí)你心理肯定有疑問,那前面提到的資源和對應(yīng)的規(guī)則去哪了?

前面在說資源概念的時(shí)候,我提到Sentinel中默認(rèn)一個(gè)http接口就是一個(gè)資源,并且資源的名稱就是接口的請求路徑。

而真正的原因是Sentinel實(shí)現(xiàn)了SpringMVC中的HandlerInterceptor接口,在調(diào)用Controller接口之前,會(huì)將一個(gè)調(diào)用接口設(shè)置為一個(gè)資源,代碼如下

55e4e290-eadc-11ed-90ce-dac502259ad0.png

getResourceName方法就是獲取資源名,其實(shí)就是接口的請求路徑,比如前面提供的接口路徑是/sayHello,那么資源名就是/sayHello

再后面的代碼就是調(diào)用上面demo中提到表面風(fēng)平浪靜,實(shí)則暗流涌動(dòng)的SphU.entry(..)方法,檢查被調(diào)用的資源是否達(dá)到了設(shè)置的規(guī)則。

好了,既然資源默認(rèn)是接口,已經(jīng)有了,那么規(guī)則呢?

規(guī)則當(dāng)然可以按照第一個(gè)demo的方式來做,比如在Controller接口中加載,代碼如下。

@RestController
publicclassSentinelDemoController{

static{
Listrules=newArrayList<>();

//創(chuàng)建一個(gè)流控規(guī)則
FlowRulerule=newFlowRule();
//對/sayHello這個(gè)資源限流
rule.setResource("/sayHello");
//基于qps限流
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//qps最大為2,超過2就要被限流
rule.setCount(2);

rules.add(rule);

//設(shè)置規(guī)則
FlowRuleManager.loadRules(rules);
}

@GetMapping("/sayHello")
publicStringsayHello()throwsInterruptedException{
return"hello";
}

}

此時(shí)啟動(dòng)項(xiàng)目,在瀏覽器輸入以下鏈接

http://localhost:9527/sayHello

瘋狂快速使勁地多點(diǎn)幾次,就出現(xiàn)下面這種情況

55f16b6e-eadc-11ed-90ce-dac502259ad0.png

可以看出規(guī)則生效了,接口被Sentinel限流了,至于為什么出現(xiàn)這個(gè)提示,是因?yàn)镾entinel有默認(rèn)的處理BlockException的機(jī)制,就在前面提到的進(jìn)入資源的后面。

55f9d240-eadc-11ed-90ce-dac502259ad0.png

當(dāng)然,你也可以自定義處理的邏輯,實(shí)現(xiàn)BlockExceptionHandler接口就可以了。

雖然上面這種硬編碼規(guī)則的方式可以使用,但是在實(shí)際的項(xiàng)目中,肯定希望能夠基于系統(tǒng)當(dāng)期那運(yùn)行的狀態(tài)來動(dòng)態(tài)調(diào)整規(guī)則,所以Sentinel提供了一個(gè)叫Dashboard應(yīng)用的控制臺(tái),可以通過控制臺(tái)來動(dòng)態(tài)修改規(guī)則。

5604a724-eadc-11ed-90ce-dac502259ad0.png

控制臺(tái)其實(shí)就是一個(gè)jar包,可以從Sentinel的github倉庫上下載,或者是通過從下面這個(gè)地址獲取。

鏈接:https://pan.baidu.com/s/1Lw8V5ab_FUq934nLWDjfaw 提取碼:obr5

之后通過java -jar命令啟動(dòng)就可以了,端口默認(rèn)8080,瀏覽器訪問http://ip:8080/#/login就可以登錄控制臺(tái)了,用戶名和密碼默認(rèn)都是sentinel。

此時(shí)服務(wù)要接入控制臺(tái),只需要在配置文件上加上控制臺(tái)的ip和端口即可

spring:
cloud:
sentinel:
transport:
#指定控制臺(tái)的ip和端口
dashboard:localhost:8080

項(xiàng)目剛啟動(dòng)的時(shí)候控制臺(tái)默認(rèn)是沒有數(shù)據(jù)的,需要訪問一下接口,之后就有了。

560f0944-eadc-11ed-90ce-dac502259ad0.png

之后就可以看到/sayHello這個(gè)資源,后面就可以通過頁面設(shè)置規(guī)則。

核心原理

講完demo,接下來就來講一講Sentinel的核心原理,也就是前面提到暗流涌動(dòng)的SphU.entry(..)這行代碼背后的邏輯。

Sentinel會(huì)為每個(gè)資源創(chuàng)建一個(gè)處理鏈條,就是一個(gè)責(zé)任鏈,第一次訪問這個(gè)資源的時(shí)候創(chuàng)建,之后就一直復(fù)用,所以這個(gè)處理鏈條每個(gè)資源有且只有一個(gè)。

SphU.entry(..)這行代碼背后就會(huì)調(diào)用責(zé)任鏈來完成對資源的檢查邏輯。

這個(gè)責(zé)任鏈條中每個(gè)處理節(jié)點(diǎn)被稱為ProcessorSlot,中文意思就是處理器槽

56188d70-eadc-11ed-90ce-dac502259ad0.png

這個(gè)ProcessorSlot有很多實(shí)現(xiàn),但是Sentinel的核心就下面這8個(gè):

  • NodeSelectorSlot
  • ClusterBuilderSlot
  • LogSlot
  • StatisticSlot
  • AuthoritySlot
  • SystemSlot
  • FlowSlot
  • DegradeSlot

這些實(shí)現(xiàn)會(huì)通過SPI機(jī)制加載,然后按照一定的順序組成一個(gè)責(zé)任鏈。

默認(rèn)情況下,節(jié)點(diǎn)是按照如下的順序進(jìn)行排序的

562551b8-eadc-11ed-90ce-dac502259ad0.png

雖然默認(rèn)就8個(gè),但是如果你想擴(kuò)展,只要實(shí)現(xiàn)ProcessorSlot,按照SPI的規(guī)定配置一下就行。

下面就來按照上面節(jié)點(diǎn)的處理順序來好好扒一扒這8個(gè)ProcessorSlot

1、NodeSelectorSlot

這個(gè)節(jié)點(diǎn)的作用是來設(shè)置當(dāng)前資源對應(yīng)的入口統(tǒng)計(jì)Node 。

首先什么是統(tǒng)計(jì)Node?

比如就拿上面的例子來說,當(dāng)/sayHello這個(gè)資源的qps超過2的時(shí)候,要觸發(fā)限流。

但是有個(gè)疑問,Sentinel是怎么知道/sayHello這個(gè)資源的qps是否達(dá)到2呢?

當(dāng)然是需要進(jìn)行數(shù)據(jù)統(tǒng)計(jì)的,只有通過統(tǒng)計(jì),才知道qps是否達(dá)到2,這個(gè)進(jìn)行數(shù)據(jù)統(tǒng)計(jì)的類在Sentinel中叫做Node。

562a5bb8-eadc-11ed-90ce-dac502259ad0.png

通過Node這個(gè)統(tǒng)計(jì)的類就知道有多少請求,成功多少個(gè),失敗多少個(gè),qps是多少之類的。底層其實(shí)是使用到了滑動(dòng)窗口算法

那么什么叫對應(yīng)的入口?

在Sentinel中,支持同一個(gè)資源有不同的訪問入口。

舉個(gè)例子,這個(gè)例子后面會(huì)反復(fù)提到。

假設(shè)把杭州看做是服務(wù),西湖看做是一個(gè)資源,到達(dá)西湖有兩種方式,地鐵和公交。

5632a7f0-eadc-11ed-90ce-dac502259ad0.png

所以要想訪問西湖這個(gè)資源,就可以通過公交和地鐵兩種方式,而公交和地鐵就對應(yīng)前面說的入口的意思。

只不過一般一個(gè)資源就一個(gè)入口,比如一個(gè)http接口一般只能通過http訪問,但是Sentinel支持多入口,你可以不用,但是Sentinel有。

所以NodeSelectorSlot的作用就是選擇資源在當(dāng)前調(diào)用入口的統(tǒng)計(jì)Node,這樣就實(shí)現(xiàn)了統(tǒng)計(jì)同一個(gè)資源在不同入口訪問數(shù)據(jù),用上面的例子解釋,就可以實(shí)現(xiàn)分別統(tǒng)計(jì)通過公交和地鐵訪問西湖的人數(shù)。

資源的入口可以在進(jìn)入資源之前通過ContextUtil.enter("入口名", origin)來指定,如果不指定,那么入口名稱默認(rèn)就是sentinel_default_context。

在SpringMVC環(huán)境底下,所有的http接口資源,默認(rèn)的入口都是sentinel_spring_web_context

563c6736-eadc-11ed-90ce-dac502259ad0.png

入口名稱也可以通過控制臺(tái)看到

5645b62e-eadc-11ed-90ce-dac502259ad0.png

那么為什么要搞一個(gè)入口的概念呢?這里咱先留個(gè)懸念,后面再說。

2、ClusterBuilderSlot

ClusterBuilderSlot的作用跟NodeSelectorSlot其實(shí)是差不多的,也是用來選擇統(tǒng)計(jì)Node,但是選擇的Node的統(tǒng)計(jì)維護(hù)跟NodeSelectorSlot不一樣。

ClusterBuilderSlot會(huì)選擇兩個(gè)統(tǒng)計(jì)Node:

  • 第一個(gè)統(tǒng)計(jì)Node是資源的所有入口的統(tǒng)計(jì)數(shù)據(jù)之和,就是資源訪問的總數(shù)據(jù)
  • 第二個(gè)統(tǒng)計(jì)Node就是統(tǒng)計(jì)資源調(diào)用者對資源訪問數(shù)據(jù)

資源調(diào)用者很好理解,比如一個(gè)http接口資源肯定會(huì)被調(diào)用,那么調(diào)用這個(gè)接口的服務(wù)或者應(yīng)用其實(shí)就是資源的調(diào)用者,但是一般資源的調(diào)用者就是指某個(gè)服務(wù),后面調(diào)用者我可能會(huì)以服務(wù)來代替。

一個(gè)接口可以被很多服務(wù)調(diào)用,所以一個(gè)資源可以很多調(diào)用者,而不同調(diào)用者都會(huì)有單獨(dú)的一個(gè)統(tǒng)計(jì)Node,用來分別統(tǒng)計(jì)不同調(diào)用者對資源的訪問數(shù)據(jù)。

舉個(gè)例子,現(xiàn)在訪問西湖這個(gè)資源的大兄弟來自上海,那么就會(huì)為上海創(chuàng)建一個(gè)統(tǒng)計(jì)Node,用來統(tǒng)計(jì)所有來自上海的人數(shù),如果是北京,那么就會(huì)為北京創(chuàng)建一個(gè)統(tǒng)計(jì)Node。

那么如何知道訪問資源來自哪個(gè)服務(wù)(調(diào)用者)呢?

也是通過ContextUtil.enter("入口名", origin)來指定,這個(gè)方法的第二個(gè)參數(shù)origin就是代表服務(wù)名的意思,默認(rèn)是空。

所以ContextUtil.enter(..)可以同時(shí)指定資源的入口和調(diào)用者,一個(gè)資源一定有入口,因?yàn)椴恢付ㄈ肟谀J(rèn)就是sentinel_default_context,但是調(diào)用者不指定就會(huì)沒有。

對于一個(gè)http請求來說,Sentinel默認(rèn)服務(wù)名需要放到S-user這個(gè)請求頭中,所以如果你想知道接口的調(diào)用服務(wù),需要在調(diào)用方發(fā)送請求的時(shí)候?qū)⒎?wù)名設(shè)置到S-user請求頭中。

當(dāng)資源所在的服務(wù)接收到請求時(shí),Sentinel就會(huì)從S-user請求頭獲取到服務(wù)名,之后再通過ContextUtil.enter("入口名", "調(diào)用者名")來設(shè)置當(dāng)前資源的調(diào)用者

5677a350-eadc-11ed-90ce-dac502259ad0.png

這里我原以為Sentinel會(huì)適配比如OpenFeign之類的框架,會(huì)自動(dòng)將服務(wù)名攜帶到請求頭中,但是我翻了一下源碼,發(fā)現(xiàn)并沒有去適配,不知道是出于什么情況的考慮。

所以這一節(jié)加上上一節(jié),我們知道了一個(gè)資源其實(shí)有三種維度的統(tǒng)計(jì)Node:

  • 分別統(tǒng)計(jì)不同入口的訪問數(shù)據(jù)
  • 統(tǒng)計(jì)所有入口訪問數(shù)據(jù)之和
  • 分別統(tǒng)計(jì)來自某個(gè)服務(wù)的訪問數(shù)據(jù)

為了方便區(qū)分,我來給這三個(gè)統(tǒng)計(jì)Node取個(gè)響亮的名字

不同入口的訪問數(shù)據(jù)就叫他DefaultNode,統(tǒng)計(jì)所有入口訪問數(shù)據(jù)之和就叫他ClusterNode,來自某個(gè)服務(wù)的訪問數(shù)據(jù)就叫他OriginNode。

是不是夠響亮!

那么他們的關(guān)系就可以用下面這個(gè)圖來表示

568212c2-eadc-11ed-90ce-dac502259ad0.png

3、LogSlot

這個(gè)Slot沒什么好說的,通過名字可以看出來,其實(shí)就是用來打印日志的。

568a3da8-eadc-11ed-90ce-dac502259ad0.png

當(dāng)發(fā)生異常,就會(huì)打印日志。

4、StatisticSlot

這個(gè)Slot就比較重要了,就是用來統(tǒng)計(jì)數(shù)據(jù)的。

前面說的NodeSelectorSlot和ClusterBuilderSlot,他們的作用就是根據(jù)資源當(dāng)前的入口和調(diào)用來源來選擇對應(yīng)的統(tǒng)計(jì)Node。

而StatisticSlot就是對這些統(tǒng)計(jì)Node進(jìn)行實(shí)際的統(tǒng)計(jì),比如加一下資源的訪問線程數(shù),資源的請求數(shù)量等等。

5692998a-eadc-11ed-90ce-dac502259ad0.png

前幾個(gè)Slot其實(shí)都是準(zhǔn)備、統(tǒng)計(jì)的作用,并沒有涉及限流降級之類的,他們是為限流降級提供數(shù)據(jù)支持的。

5、AuthoritySlot

Authority是授權(quán)的意思,這個(gè)Slot的作用是對資源調(diào)用者進(jìn)行授權(quán),就是黑白名單控制。

可以通過控制臺(tái)來添加授權(quán)規(guī)則。

569cd576-eadc-11ed-90ce-dac502259ad0.png

在AuthoritySlot中會(huì)去獲取資源的調(diào)用者,之后會(huì)跟授權(quán)規(guī)則中的資源應(yīng)用這個(gè)選項(xiàng)進(jìn)行匹配,之后就會(huì)出現(xiàn)有以下2種情況:

  • 授權(quán)類型是黑名單,匹配上了,說明在黑名單內(nèi),那么這個(gè)服務(wù)就不能訪問這個(gè)資源,沒匹配上就可以訪問
  • 授權(quán)類型是白名單。匹配上了,說明在白名單內(nèi),那么這個(gè)服務(wù)就可以訪問這個(gè)資源,沒匹配上就不可以訪問

6、SystemSlot

這個(gè)的作用是根據(jù)整個(gè)系統(tǒng)運(yùn)行的統(tǒng)計(jì)數(shù)據(jù)來限流的,防止當(dāng)前系統(tǒng)負(fù)載過高。

它支持入口qps、線程數(shù)、響應(yīng)時(shí)間、cpu使用率、負(fù)載5個(gè)限流的維度。

56a7c4ae-eadc-11ed-90ce-dac502259ad0.png

對于系統(tǒng)的入口qps、線程數(shù)、平均響應(yīng)時(shí)間這些指標(biāo),也會(huì)有一個(gè)統(tǒng)計(jì)Node專門去統(tǒng)計(jì),所以這個(gè)統(tǒng)計(jì)Node的作用就好比會(huì)去統(tǒng)計(jì)所有訪問西湖的人數(shù),統(tǒng)計(jì)也在StatisticSlot代碼中,前面說的時(shí)候我把代碼隱藏了

56b2147c-eadc-11ed-90ce-dac502259ad0.png

至于cpu使用率、負(fù)載指標(biāo),Sentinel會(huì)啟動(dòng)一個(gè)定時(shí)任務(wù),每隔1s會(huì)去讀取一次當(dāng)前系統(tǒng)的cpu和負(fù)載。

7、FlowSlot

這個(gè)Slot會(huì)根據(jù)預(yù)設(shè)的規(guī)則,結(jié)合前面的統(tǒng)計(jì)出來的實(shí)時(shí)信息進(jìn)行流量控制。

在說FlowSlot之前,先來用之前畫的那張圖回顧一下一個(gè)資源的三種統(tǒng)計(jì)維度

568212c2-eadc-11ed-90ce-dac502259ad0.png

這里默默地注視10s。。

限流規(guī)則配置項(xiàng)比較多

56cc829e-eadc-11ed-90ce-dac502259ad0.png

這里我們來好好扒一扒這些配置項(xiàng)的意思。

針對來源 ,來源就是前面說的調(diào)用方,這個(gè)配置表明,這個(gè)規(guī)則適用于哪個(gè)調(diào)用方,默認(rèn)是default,就是指規(guī)則適用于所有調(diào)用方,如果指定了調(diào)用方,那么這個(gè)規(guī)則僅僅對指定的調(diào)用方生效。

舉個(gè)例子來說,比如說現(xiàn)在想限制來自上海的訪問的人數(shù),那么針對來源可以填上海,之后當(dāng)訪問的大兄弟來自上海的時(shí)候,Sentinel就會(huì)根據(jù)上海對應(yīng)的OriginNode數(shù)據(jù)來判斷是否達(dá)到限流的條件。

閾值類型 ,就是限流條件,當(dāng)資源的qps或者訪問的線程數(shù)到達(dá)設(shè)置的單機(jī)閾值,就會(huì)觸發(fā)限流。

是否集群 ,這個(gè)作用是用來對集群控制的,因?yàn)橐粋€(gè)服務(wù)可能在很多臺(tái)機(jī)器上,而這個(gè)的作用就是將整個(gè)集群看成一個(gè)整體來限流,這里就不做深入討論。

流控模式 ,這個(gè)流控模式的選項(xiàng)僅僅對閾值類型為qps有效,當(dāng)閾值類型線程數(shù)時(shí)無效。

這個(gè)配置就比較有意思了,分為直接、關(guān)聯(lián)、鏈路三種模式。

直接模式的意思就是當(dāng)資源的ClusterNode統(tǒng)計(jì)數(shù)據(jù)統(tǒng)計(jì)達(dá)到了閾值,就會(huì)觸發(fā)限流。

比如,當(dāng)通過地鐵和公交訪問西湖人數(shù)之和達(dá)到單機(jī)閾值之后就會(huì)觸發(fā)限流。

關(guān)聯(lián)模式下需要填寫關(guān)聯(lián)的資源名稱

56d55252-eadc-11ed-90ce-dac502259ad0.png

關(guān)聯(lián)的意思就是當(dāng)關(guān)聯(lián)資源 的ClusterNode統(tǒng)計(jì)的qps達(dá)到了設(shè)置的閾值時(shí),就會(huì)觸發(fā)當(dāng)前資源 的限流操作。

比如,假設(shè)現(xiàn)在西湖這個(gè)資源關(guān)聯(lián)了雷峰塔這個(gè)資源,那么當(dāng)訪問雷峰塔的人數(shù)達(dá)到了指定的閾值之后,此時(shí)就觸發(fā)西湖這個(gè)資源的限流,就是雷峰塔流量高了但是限流的是西湖。

鏈路模式也一樣,它需要關(guān)聯(lián)一個(gè)入口資源

56dfaba8-eadc-11ed-90ce-dac502259ad0.png

關(guān)聯(lián)入口的意思就是指,當(dāng)訪問資源的實(shí)際入口跟關(guān)聯(lián)入口是一樣的時(shí)候,就會(huì)根據(jù)這個(gè)入口對應(yīng)的DefaultNode的統(tǒng)計(jì)數(shù)據(jù)來判斷是否需要限流。

也就是可以單獨(dú)限制通過公交和地鐵的訪問的人數(shù)的意思。

到這,其實(shí)前面說到的一個(gè)資源的三種統(tǒng)計(jì)維度的數(shù)據(jù)都用到了,現(xiàn)在應(yīng)該明白了為什么需要這么多維度的數(shù)據(jù),就是為不同維度限流準(zhǔn)備的。

最后一個(gè)配置項(xiàng),流控效果 ,這個(gè)就是如果是通過qps來限流,并且達(dá)到了限流的條件之后會(huì)做什么,如果是線程數(shù),就直接拋出BlockException異常

也有三種方式,快速失敗、Warm Up、排隊(duì)等待

快速失敗的意思就是指一旦觸發(fā)限流了,那么直接拋出BlockException異常

Warm Up的作用就是為了防止系統(tǒng)流量突然增加時(shí)出現(xiàn)瞬間把系統(tǒng)壓垮的情況。通過"冷啟動(dòng)",讓通過的流量緩慢增加,在一定時(shí)間內(nèi)逐漸增加到閾值上限。

排隊(duì)等待,很好理解,意思當(dāng)出現(xiàn)限流了,不是拋異常,而是去排隊(duì)等待一定時(shí)間,其實(shí)就是讓請求均勻速度通過,內(nèi)部使用的是傳說中的漏桶算法。

DegradeSlot

這是整個(gè)責(zé)任鏈中最后一個(gè)slot,這個(gè)slot的作用是用來熔斷降級的。

Sentinel支持三種熔斷策略:慢調(diào)用比例、異常比例 、異常數(shù),通過規(guī)則配置也可以看出來。

56e99834-eadc-11ed-90ce-dac502259ad0.png

熔斷器的工作流程大致如下

56f6a790-eadc-11ed-90ce-dac502259ad0.png

Sentinel會(huì)為每個(gè)設(shè)置的規(guī)則都創(chuàng)建一個(gè)熔斷器,熔斷器有三種狀態(tài),OPEN(打開)、HALF_OPEN(半開)、CLOSED(關(guān)閉)

  • 當(dāng)處于CLOSED狀態(tài)時(shí),可以訪問資源,訪問之后會(huì)進(jìn)行慢調(diào)用比例、異常比例、異常數(shù)的統(tǒng)計(jì),一旦達(dá)到了設(shè)置的閾值,就會(huì)將熔斷器的狀態(tài)設(shè)置為OPEN
  • 當(dāng)處于OPEN狀態(tài)時(shí),會(huì)去判斷是否達(dá)到了熔斷時(shí)間,如果沒到,拒絕訪問,如果到了,那么就將狀態(tài)改成HALF_OPEN,然后訪問資源,訪問之后會(huì)對訪問結(jié)果進(jìn)行判斷,符合規(guī)則設(shè)置的要求,直接將熔斷器設(shè)置為CLOSED,關(guān)閉熔斷器,不符合則還是改為OPEN狀態(tài)
  • 當(dāng)處于HALF_OPEN狀態(tài)時(shí),直接拒絕訪問資源

一般來說,熔斷降級其實(shí)是對于服務(wù)的調(diào)用方來說的。

在項(xiàng)目中會(huì)經(jīng)常調(diào)用其它服務(wù)或者是第三方接口,而對于這些接口,一旦它們出現(xiàn)不穩(wěn)定,就有可能導(dǎo)致自身服務(wù)長時(shí)間等待,從而出現(xiàn)響應(yīng)延遲等等問題。

此時(shí)服務(wù)調(diào)用方就可基于熔斷降級方式解決。

一旦第三方接口響應(yīng)時(shí)間過長,那么就可以使用慢調(diào)用比例規(guī)則,當(dāng)出現(xiàn)大量長時(shí)間響應(yīng)的情況,那么就直接熔斷,不去請求。

雖然說熔斷降級是針對服務(wù)的調(diào)用方來說,但是Sentinel本身并沒有限制熔斷降級一定是調(diào)用其它的服務(wù)。

總結(jié)

通過整篇文章的分析之后,再回頭看看Sentinel的簡介的內(nèi)容,其實(shí)就能更好地理解Sentinel的定位和擁有的強(qiáng)大功能。

Sentinel核心就是一堆統(tǒng)計(jì)數(shù)據(jù)和基于這些統(tǒng)計(jì)數(shù)據(jù)實(shí)現(xiàn)的流控和熔斷的功能,源碼并不復(fù)雜,而且Sentinel的代碼寫得非常好。

最后奉上Sentinel源碼注釋倉庫地址:

https://github.com/sanyou3/sentinel.git

還有本文demo代碼倉庫地址:

https://github.com/sanyou3/sentinel-demo.git



審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    626

    瀏覽量

    28981
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4673

    瀏覽量

    67792
  • Sentinel
    +關(guān)注

    關(guān)注

    0

    文章

    9

    瀏覽量

    7130

原文標(biāo)題:Sentinel為什么這么強(qiáng),我扒了扒背后的實(shí)現(xiàn)原理

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    與無線網(wǎng)絡(luò)相關(guān)的那些事

    事是詢問服務(wù)員店內(nèi)無線網(wǎng)絡(luò)的密碼而不是點(diǎn)菜。店員給我說,搜索VTache-XXX熱點(diǎn),就可以連接上網(wǎng)啦。真還別說連上去,上網(wǎng)認(rèn)證的方式很多(微博、微信、QQ、手機(jī)號),還是選擇微信登錄,是指尖這么一點(diǎn)啊
    發(fā)表于 05-27 11:40

    看過的那些Linux相關(guān)的書籍

    來北京工作已經(jīng)一個(gè)多月,大都市的生活比起讀大學(xué)要忙碌得多,尤其是出行,基本以小時(shí)為基本的計(jì)時(shí)單位。有時(shí)茫然看著窗外車水馬龍,會(huì)有些迷茫自己選擇的是對還是錯(cuò)。  題外話不多說,回歸這次的主題,
    發(fā)表于 07-04 06:39

    渣機(jī)產(chǎn)品有哪些參數(shù)

    配套使用可實(shí)現(xiàn)煤礦掘進(jìn)機(jī)械化作業(yè),大大提高掘進(jìn)速度,可適用于斷面為2.1×2.1米以上,坡度±1 8 度的巷道?! ?b class='flag-5'>扒取力大,裝載能力強(qiáng)。采用密封潤滑式履帶,張緊履帶裝置調(diào)節(jié)方便,使用壽命長;采用挖掘機(jī)專用斗齒堅(jiān)固耐用,互換性好
    發(fā)表于 09-02 08:00

    C語言hello world背后的內(nèi)幕

    ;#125;不用多說,這段程序在運(yùn)行時(shí),會(huì)在顯示終端上打印出 hello world 。那么,這段程序背后關(guān)聯(lián)的內(nèi)容,你是否真正梳理明白呢?源程序代碼是如何編譯成可執(zhí)行程序的?#include&
    發(fā)表于 09-30 10:31

    華為P10這么早被光,目的只有一個(gè)!懟肛小米6

    按照華為P系列的迭代速度每年新機(jī)發(fā)布一般都在4月10號左右,并且發(fā)布地一般都會(huì)選擇歐洲,過去都是在英國,可是現(xiàn)在英國已經(jīng)脫歐,華為P10會(huì)在哪里發(fā)布呢?發(fā)布地不重要,重要的是華為P10近幾天已經(jīng)快讓底褲都給光了。
    發(fā)表于 01-23 14:10 ?1756次閱讀

    美容儀哪個(gè)牌子好?來令人眼花繚亂的日本美容儀

    獲得了大眾的喜愛。美容儀哪個(gè)牌子好?小編給你日本的美容儀神器品牌。 我們都知道,日本是個(gè)科技大國,不管是電器類還是美容儀類,都收獲世界大批粉絲的追捧,市面上的美容儀品牌多種多樣,價(jià)格相差也大,各大美容儀從洗臉到瘦臉
    發(fā)表于 04-16 19:50 ?9805次閱讀
    美容儀哪個(gè)牌子好?來<b class='flag-5'>扒</b>一<b class='flag-5'>扒</b>令人眼花繚亂的日本美容儀

    好用的日本家用美容儀品牌,讓你享受清潔肌膚的樂趣

    現(xiàn)在人們的生活水平逐漸提高,科技也越來越發(fā)達(dá),使得人們可以有更多的選擇。市面上的醫(yī)美機(jī)構(gòu)參差不齊,雜牌美容院的毀容新聞?lì)l現(xiàn)報(bào)道,這就讓不少想嘗試醫(yī)美的消費(fèi)者望而卻步,于是,美容儀市場就興起
    發(fā)表于 06-04 21:03 ?812次閱讀

    店saas系統(tǒng)創(chuàng)新性服務(wù)平臺(tái)的優(yōu)勢是什么

    店在手,天下有,現(xiàn)在市面上有很多的店鋪管理saas系統(tǒng),在日益成熟的商業(yè)大環(huán)境和店鋪需求下,店鋪管理系統(tǒng)技術(shù)也趨于成熟,越來越多的商家不再局限于店鋪的收銀管理這種常規(guī)系統(tǒng)功能,所以新的店鋪系統(tǒng)
    的頭像 發(fā)表于 10-15 10:14 ?1996次閱讀

    中斷為什么不能調(diào)printf?

    前面說會(huì)寫一下Modbus-RTU的實(shí)現(xiàn),寫了1000多字,有興趣的稍等一下哈。前面在一個(gè)群里看到一個(gè)朋友在一個(gè)串口接收中斷里打印遇到了問題,今天聊下這個(gè)話題。printf對于
    發(fā)表于 12-04 12:21 ?0次下載
    <b class='flag-5'>扒</b>一<b class='flag-5'>扒</b>中斷為什么不能調(diào)printf?

    一個(gè)超棒的stm32的開源usb-can項(xiàng)目,canable及PCAN固件

    一個(gè)超棒的stm32的開源usb-can項(xiàng)目,canable及PCAN固件
    發(fā)表于 12-20 18:55 ?35次下載
    <b class='flag-5'>扒</b>一個(gè)超棒的stm32的開源usb-can項(xiàng)目,canable及PCAN固件

    中斷為什么不能調(diào)printf

    [導(dǎo)讀] 大家好,是逸珺。前面說會(huì)寫一下Modbus-RTU的實(shí)現(xiàn),寫了1000多字,有興趣的稍等一下哈。前面在一個(gè)群里看到一個(gè)朋友在一個(gè)串...
    發(fā)表于 01-25 17:52 ?0次下載
    <b class='flag-5'>扒</b>一<b class='flag-5'>扒</b>中斷為什么不能調(diào)printf

    雕銑機(jī)、雕刻機(jī)和加工中心之間的區(qū)別

    中心、雕銑機(jī)、雕刻機(jī),之間有什么區(qū)別?相信這句話很多剛剛加入這個(gè)圈的朋友都會(huì)問,然后在買機(jī)械設(shè)備的時(shí)候不太懂,不知道怎么區(qū)分,到底應(yīng)該買什么樣的設(shè)備,才能達(dá)到自己的需求,今天小編就為大家他們?nèi)咧g的區(qū)別。
    的頭像 發(fā)表于 01-15 09:48 ?540次閱讀

    晶振頻率漂移的原因

    晶振頻率漂移的原因? 晶振頻率漂移是指晶振器輸出頻率在長時(shí)間使用中逐漸偏離其標(biāo)稱頻率的現(xiàn)象。晶振頻率漂移是一種晶振器的固有性能,其原因主要取決于晶振器的制造工藝、環(huán)境條件、使用方式以及壽命等
    的頭像 發(fā)表于 01-26 14:20 ?682次閱讀

    折疊屏手機(jī)背后的“黑科技”

    折疊屏手機(jī)似乎正成為各大品牌下一步推新的產(chǎn)品,那么今天,就讓我們這里面到底有什么“黑科技”。
    的頭像 發(fā)表于 02-26 10:34 ?952次閱讀
    <b class='flag-5'>扒</b>一<b class='flag-5'>扒</b>折疊屏手機(jī)<b class='flag-5'>背后</b>的“黑科技”

    渣機(jī)遠(yuǎn)程監(jiān)控運(yùn)維管理系統(tǒng)解決方案

    渣機(jī)主要由機(jī)械手與輸送機(jī)相結(jié)合,將自動(dòng)渣和自動(dòng)輸送功能合二為一,替代傳統(tǒng)的人工和間歇式機(jī)械作業(yè),大大提高了工作效率,降低了勞動(dòng)強(qiáng)度,并顯著提升了作業(yè)安全性,在礦山、道路、隧道、水利等工程領(lǐng)域
    的頭像 發(fā)表于 09-05 17:10 ?101次閱讀