超詳細(xì)的Sentinel入門
文章已收錄Github精選,歡迎Star:https://github.com/yehongzhi/learningSummary
一、什么是Sentinel
Sentinel定位是分布式系統(tǒng)的流量防衛(wèi)兵。目前互聯(lián)網(wǎng)應(yīng)用基本上都使用微服務(wù),微服務(wù)的穩(wěn)定性是一個(gè)很重要的問題,而限流、熔斷降級(jí)是微服務(wù)保持穩(wěn)定的一個(gè)重要的手段。
下面看官網(wǎng)的一張圖,了解一下Sentinel的主要特性:

在Sentinel之前其實(shí)就有Hystrix做熔斷降級(jí)的事情,我們都知道出現(xiàn)新的事物肯定是原來的東西有不足的地方。
那Hystrix有什么不足之處呢?
Hystrix常用的線程池隔離會(huì)造成線程上下切換的overhead比較大。 Hystrix沒有監(jiān)控平臺(tái),需要我們自己搭建。 Hystrix支持的熔斷降級(jí)維度較少,不夠細(xì)粒,而且缺少管理控制臺(tái)。
Sentinel有哪些組成部分?
核心庫(Java 客戶端)不依賴任何框架/庫,能夠運(yùn)行于所有 Java 運(yùn)行時(shí)環(huán)境,同時(shí)對(duì) Dubbo / Spring Cloud 等框架也有較好的支持。 控制臺(tái)(Dashboard)基于 Spring Boot 開發(fā),打包后可以直接運(yùn)行,不需要額外的 Tomcat 等應(yīng)用容器。
Sentinel有哪些特征?
豐富的應(yīng)用場(chǎng)景。控制突發(fā)流量在可控制的范圍內(nèi),消息削峰填谷,集群流量控制,實(shí)時(shí)熔斷下游不可用的應(yīng)用等等。
完備的實(shí)時(shí)監(jiān)控。Sentinel 提供實(shí)時(shí)的監(jiān)控功能。您可以在控制臺(tái)中看到接入應(yīng)用的單臺(tái)機(jī)器秒級(jí)數(shù)據(jù),甚至 500 臺(tái)以下規(guī)模的集群的匯總運(yùn)行情況。
廣泛的開源生態(tài)。Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應(yīng)的依賴并進(jìn)行簡(jiǎn)單的配置即可快速地接入 Sentinel。
完善的 SPI 擴(kuò)展點(diǎn)。Sentinel 提供簡(jiǎn)單易用、完善的 SPI 擴(kuò)展接口。您可以通過實(shí)現(xiàn)擴(kuò)展接口來快速地定制邏輯。例如定制規(guī)則管理、適配動(dòng)態(tài)數(shù)據(jù)源等。
二、Hello World
一般要學(xué)一種沒接觸過的技術(shù)框架,肯定要先做個(gè)Hello World熟悉一下。
引入Maven依賴
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.1</version>
</dependency>
需要提醒一下,Sentinel僅支持JDK 1.8或者以上的版本
定義規(guī)則
通過定義規(guī)則來控制該資源每秒允許通過的請(qǐng)求次數(shù),例如下面的代碼定義了資源 HelloWorld 每秒最多只能通過 20 個(gè)請(qǐng)求。
private static void initFlowRules(){
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("HelloWorld");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// Set limit QPS to 20.
rule.setCount(20);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
編寫Hello World代碼
其實(shí)代碼編寫很簡(jiǎn)單,首先需要定義一個(gè)資源entry,然后用SphU.entry("HelloWorld")和entry.exit()把需要流量控制的代碼包圍起來。代碼如下:
public static void main(String[] args) throws Exception {
initFlowRules();
while (true) {
Entry entry = null;
try {
entry = SphU.entry("HelloWorld");
/*您的業(yè)務(wù)邏輯 - 開始*/
System.out.println("hello world");
/*您的業(yè)務(wù)邏輯 - 結(jié)束*/
} catch (BlockException e1) {
/*流控邏輯處理 - 開始*/
System.out.println("block!");
/*流控邏輯處理 - 結(jié)束*/
} finally {
if (entry != null) {
entry.exit();
}
}
}
}
運(yùn)行結(jié)果如下:

我們根據(jù)目錄查看日志,文件名格式為${appName}-metrics.log.xxx:
|--timestamp-|------date time----|-resource-|p |block|s |e|rt
1616607101000|2021-03-25 01:31:41|HelloWorld|20|11373|20|0|1|0|0|0
1616607102000|2021-03-25 01:31:42|HelloWorld|20|24236|20|0|0|0|0|0
p 代表通過的請(qǐng)求。
block 代表被阻止的請(qǐng)求。
s 代表成功執(zhí)行完成的請(qǐng)求個(gè)數(shù)。
e 代表用戶自定義的異常。
rt 代表平均響應(yīng)時(shí)長(zhǎng)。
三、使用Sentinel的方式
下面結(jié)合實(shí)際案例,寫一個(gè)Controller接口進(jìn)行示范練習(xí)。
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserService userService;
@RequestMapping("/list")
public List<User> getUserList() {
return userService.getList();
}
}
@Service
public class UserServiceImpl implements UserService {
//模擬查詢數(shù)據(jù)庫數(shù)據(jù),返回結(jié)果
@Override
public List<User> getList() {
List<User> userList = new ArrayList<>();
userList.add(new User("1", "周慧敏", 18));
userList.add(new User("2", "關(guān)之琳", 20));
userList.add(new User("3", "王祖賢", 21));
return userList;
}
}
假設(shè)我們要讓這個(gè)查詢接口限流,怎么做呢?
1) 拋出異常的方式
SphU 包含了 try-catch 風(fēng)格的 API。用這種方式,當(dāng)資源發(fā)生了限流之后會(huì)拋出 BlockException。這個(gè)時(shí)候可以捕捉異常,進(jìn)行限流之后的邏輯處理。
@RestController
@RequestMapping("/user")
public class UserController {
//資源名稱
public static final String RESOURCE_NAME = "userList";
@Resource
private UserService userService;
@RequestMapping("/list")
public List<User> getUserList() {
List<User> userList = null;
Entry entry = null;
try {
// 被保護(hù)的業(yè)務(wù)邏輯
entry = SphU.entry(RESOURCE_NAME);
userList = userService.getList();
} catch (BlockException e) {
// 資源訪問阻止,被限流或被降級(jí)
return Collections.singletonList(new User("xxx", "資源訪問被限流", 0));
} catch (Exception e) {
// 若需要配置降級(jí)規(guī)則,需要通過這種方式記錄業(yè)務(wù)異常
Tracer.traceEntry(e, entry);
} finally {
// 務(wù)必保證 exit,務(wù)必保證每個(gè) entry 與 exit 配對(duì)
if (entry != null) {
entry.exit();
}
}
return userList;
}
}
實(shí)際上還沒寫完,還要定義限流的規(guī)則。
@SpringBootApplication
public class SpringmvcApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(SpringmvcApplication.class, args);
//初始化限流規(guī)則
initFlowQpsRule();
}
//定義了每秒最多接收2個(gè)請(qǐng)求
private static void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule(UserController.RESOURCE_NAME);
// set limit qps to 2
rule.setCount(2);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
然后啟動(dòng)項(xiàng)目,測(cè)試。快速刷新幾次,我們就看到觸發(fā)限流的邏輯了。

2) 返回布爾值的方式
拋出異常的方式是當(dāng)被限流時(shí)以拋出異常的形式感知,我們通過捕獲異常進(jìn)行限流的處理,這種方式跟上面不同的在于不拋出異常,而是返回一個(gè)布爾值,我們通過判斷布爾值來進(jìn)行限流邏輯的處理。這樣我們就可以很容易寫出if-else結(jié)構(gòu)的代碼。
public static final String RESOURCE_NAME_QUERY_USER_BY_ID = "queryUserById";
@RequestMapping("/get/{id}")
public String queryUserById(@PathVariable("id") String id) {
if (SphO.entry(RESOURCE_NAME_QUERY_USER_BY_ID)) {
try {
//被保護(hù)的邏輯
//模擬數(shù)據(jù)庫查詢數(shù)據(jù)
return JSONObject.toJSONString(new User(id, "Tom", 25));
} finally {
//關(guān)閉資源
SphO.exit();
}
} else {
//資源訪問阻止,被限流或被降級(jí)
return "Resource is Block!!!";
}
}
添加規(guī)則的代碼跟前面的例子一樣,我就不寫了,然后啟動(dòng)項(xiàng)目,測(cè)試。

3) 注解的方式
看了上面兩種方式,肯定有人會(huì)說,代碼侵入性太強(qiáng)了,如果原來舊的系統(tǒng)要接入的話,要改原來的代碼。眾所周知,舊代碼是不能動(dòng)的,否則后果很嚴(yán)重。
那么注解的方式就很好地解決了這個(gè)問題。注解式怎么寫呢?
@Service
public class UserServiceImpl implements UserService {
//資源名稱
public static final String RESOURCE_NAME_QUERY_USER_BY_NAME = "queryUserByUserName";
//value是資源名稱,是必填項(xiàng)。blockHandler填限流處理的方法名稱
@Override
@SentinelResource(value = RESOURCE_NAME_QUERY_USER_BY_NAME, blockHandler = "queryUserByUserNameBlock")
public User queryByUserName(String userName) {
return new User("0", userName, 18);
}
//注意細(xì)節(jié),一定要跟原函數(shù)的返回值和形參一致,并且形參最后要加個(gè)BlockException參數(shù)
//否則會(huì)報(bào)錯(cuò),F(xiàn)lowException: null
public User queryUserByUserNameBlock(String userName, BlockException ex) {
//打印異常
ex.printStackTrace();
return new User("xxx", "用戶名稱:{" + userName + "},資源訪問被限流", 0);
}
}
寫完這個(gè)核心代碼后,還要加個(gè)配置,否則不生效。
引入sentinel-annotation-aspectj的Maven依賴。
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.1</version>
</dependency>
然后將SentinelResourceAspect注冊(cè)為一個(gè)Bean。
@Configuration
public class SentinelAspectConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
別忘了添加規(guī)則,可以參考第一個(gè)例子,這里就不寫了。
最后啟動(dòng)項(xiàng)目,測(cè)試,刷新多幾次接口后,出發(fā)限流,可以看到以下結(jié)果。

4) 熔斷降級(jí)
除了可以對(duì)接口進(jìn)行限流之外,當(dāng)接口出現(xiàn)異常時(shí),Sentinel也可以提供熔斷降級(jí)的功能。
在@SentinelResource注解中有一個(gè)屬性fallback,當(dāng)拋出非BlockException的異常時(shí),就會(huì)進(jìn)入到fallback方法中,實(shí)現(xiàn)熔斷機(jī)制,這有點(diǎn)類似于Hystrix的FallBack。
我們拿上面的例子做示范,如果userName為空則拋出RuntimeException。然后我們?cè)O(shè)置fallback屬性的屬性值,也就是fallback的方法,返回系統(tǒng)異常。
@Override
@SentinelResource(value = RESOURCE_NAME_QUERY_USER_BY_NAME, blockHandler = "queryUserByUserNameBlock", fallback = "queryUserByUserNameFallBack")
public User queryByUserName(String userName) {
if (userName == null || "".equals(userName)) {
//拋出異常
throw new RuntimeException("queryByUserName() command failed, userName is null");
}
return new User("0", userName, 18);
}
public User queryUserByUserNameFallBack(String userName, Throwable ex) {
//打印日志
ex.printStackTrace();
return new User("-1", "用戶名稱:{" + userName + "},系統(tǒng)異常,請(qǐng)稍后重試", 0);
}
然后啟動(dòng)項(xiàng)目,故意不傳userName,進(jìn)行測(cè)試,可以看到走了fallback的方法邏輯。

IDEA控制臺(tái)也可以看到自定義的異常信息。

四、管理控制臺(tái)
上面講完了Sentinel的基本用法,實(shí)際上重頭戲在Sentinel的管理控制臺(tái),管理控制臺(tái)提供了很多實(shí)用的功能。下面我們看看怎么使用。
首先下載控制臺(tái)的jar包,當(dāng)然你也可以通過下載源碼編譯得到。
//下載頁面地址
https://github.com/alibaba/Sentinel/releases
然后使用以下命令啟動(dòng):
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar
啟動(dòng)成功后,訪問http://localhost:8080,默認(rèn)登錄的用戶名和密碼都是sentinel。

登錄進(jìn)去之后,可以看到主頁面,有許多功能菜單,這里就不一一介紹了。

客戶端接入控制臺(tái)
那么我們自己的應(yīng)用怎么接入到控制臺(tái),使用控制臺(tái)對(duì)應(yīng)用的流量進(jìn)行監(jiān)控呢,諸位客官,請(qǐng)繼續(xù)往下看。
首先添加maven依賴,客戶端需要引入 Transport 模塊來與 Sentinel 控制臺(tái)進(jìn)行通信。
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.1</version>
</dependency>
配置filter,把所有訪問的 Web URL 自動(dòng)統(tǒng)計(jì)為 Sentinel 的資源。
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean sentinelFilterRegistration() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
registration.setFilter(new CommonFilter());
registration.addUrlPatterns("/*");
registration.setName("sentinelFilter");
registration.setOrder(1);
return registration;
}
}
在啟動(dòng)命令中加入以下配置,-Dcsp.sentinel.dashboard.server=consoleIp:port 指定控制臺(tái)地址和端口,-Dcsp.sentinel.api.port=xxxx 指定客戶端監(jiān)控 API 的端口(默認(rèn)是8019,因?yàn)榭刂婆_(tái)已經(jīng)使用了8719,應(yīng)用端為了防止沖突就使用8720):
-Dserver.port=8888 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dcsp.sentinel.api.port=8720 -Dproject.name=sentinelDemo

啟動(dòng)項(xiàng)目,我們可以看到多了一個(gè)應(yīng)用名稱sentinelDemo,點(diǎn)擊機(jī)器列表,查看健康狀況。

請(qǐng)求/user/list接口,然后我們可以看到實(shí)時(shí)監(jiān)控的接口的QPS情況。

這樣就代表客戶端接入控制臺(tái)成功了!
動(dòng)態(tài)規(guī)則
Sentinel 的理念是開發(fā)者只需要關(guān)注資源的定義,當(dāng)資源定義成功后可以動(dòng)態(tài)增加各種流控降級(jí)規(guī)則。Sentinel 提供兩種方式修改規(guī)則:
通過 API 直接修改 ( loadRules)通過 DataSource適配不同數(shù)據(jù)源修改
手動(dòng)通過API定義規(guī)則,前面Hello World的例子已經(jīng)寫過,是一種硬編碼的形式,因?yàn)椴粔蜢`活,所以肯定不能應(yīng)用于生產(chǎn)環(huán)境。
所以要引入DataSource,規(guī)則設(shè)置可以存儲(chǔ)在數(shù)據(jù)源中,通過更新數(shù)據(jù)源中存儲(chǔ)的規(guī)則,推送到Sentinel規(guī)則中心,客戶端就可以實(shí)時(shí)獲取最新的規(guī)則,根據(jù)最新的規(guī)則進(jìn)行限流、降級(jí)。
一般DataSource拓展常見的實(shí)現(xiàn)方式有:
拉模式:客戶端主動(dòng)向某個(gè)規(guī)則管理中心定期輪詢拉取規(guī)則,這個(gè)規(guī)則中心可以是SQL、文件等。優(yōu)點(diǎn)是比較簡(jiǎn)單,缺點(diǎn)是無法及時(shí)獲取變更。 推模式:規(guī)則中心統(tǒng)一推送,客戶端通過注冊(cè)監(jiān)聽器的方式時(shí)刻監(jiān)聽變化,比如使用Nacos、Zookeeper 等配置中心。這種方式有更好的實(shí)時(shí)性和一致性保證,比較推薦使用這種方式。
拉模式
pull模式的數(shù)據(jù)源一般是可寫入的(比如本地文件)。首先要在客戶端注冊(cè)數(shù)據(jù)源,將對(duì)應(yīng)的讀數(shù)據(jù)源注冊(cè)至對(duì)應(yīng)的 RuleManager;然后將寫數(shù)據(jù)源注冊(cè)至 transport 的 WritableDataSourceRegistry 中。
由此看出這是一個(gè)雙向讀寫的過程,我們既可以在應(yīng)用本地直接修改文件來更新規(guī)則,也可以通過 Sentinel 控制臺(tái)推送規(guī)則。下圖為控制臺(tái)推送規(guī)則的流程圖。

首先引入maven依賴。
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
<version>1.8.1</version>
</dependency>
使用SPI機(jī)制進(jìn)行擴(kuò)展,創(chuàng)建一個(gè)實(shí)現(xiàn)類,實(shí)現(xiàn)InitFunc接口的init()方法。
public class FileDataSourceInit implements InitFunc {
public FileDataSourceInit() {
}
@Override
public void init() throws Exception {
String filePath = System.getProperty("user.home") + "\\sentinel\\rules\\sentinel.json";
ReadableDataSource<String, List<FlowRule>> ds = new FileRefreshableDataSource<>(
filePath, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
})
);
// 將可讀數(shù)據(jù)源注冊(cè)至 FlowRuleManager.
FlowRuleManager.register2Property(ds.getProperty());
WritableDataSource<List<FlowRule>> wds = new FileWritableDataSource<>(filePath, this::encodeJson);
// 將可寫數(shù)據(jù)源注冊(cè)至 transport 模塊的 WritableDataSourceRegistry 中.
// 這樣收到控制臺(tái)推送的規(guī)則時(shí),Sentinel 會(huì)先更新到內(nèi)存,然后將規(guī)則寫入到文件中.
WritableDataSourceRegistry.registerFlowDataSource(wds);
}
private <T> String encodeJson(T t) {
return JSON.toJSONString(t);
}
}
在項(xiàng)目的 resources/META-INF/services 目錄下創(chuàng)建文件,名為com.alibaba.csp.sentinel.init.InitFunc ,內(nèi)容則是FileDataSourceInit的全限定名稱:
io.github.yehongzhi.springmvc.config.FileDataSourceInit

接著在${home}目錄下,創(chuàng)建\sentinel\rules目錄,再創(chuàng)建sentinel.json文件。

然后啟動(dòng)項(xiàng)目,發(fā)送請(qǐng)求,當(dāng)客戶端接收到請(qǐng)求后就會(huì)觸發(fā)初始化操作。初始化完成后我們到控制臺(tái),然后設(shè)置流量限流規(guī)則。

新增后,本地文件sentinel.json同時(shí)也保存了規(guī)則內(nèi)容(壓縮成一行的json)。
[{"clusterConfig":{"acquireRefuseStrategy":0,"clientOfflineTime":2000,"fallbackToLocalWhenFail":true,"resourceTimeout":2000,"resourceTimeoutStrategy":0,"sampleCount":10,"strategy":0,"thresholdType":0,"windowIntervalMs":1000},"clusterMode":false,"controlBehavior":0,"count":3.0,"grade":1,"limitApp":"default","maxQueueingTimeMs":500,"resource":"userList","strategy":0,"warmUpPeriodSec":10}]
我們可以通過修改文件來更新規(guī)則內(nèi)容,也可以通過控制臺(tái)推送規(guī)則到文件中,這就是拉模式。缺點(diǎn)是不保證一致性,實(shí)時(shí)性不保證,拉取過于頻繁也可能會(huì)有性能問題。
推模式
剛剛說了拉模式實(shí)時(shí)性不能保證,推模式就解決了這個(gè)問題。除此之外還可以持久化,也就是數(shù)據(jù)保存在數(shù)據(jù)源中,即使重啟也不會(huì)丟失之前的配置,這也解決了原始模式存在內(nèi)存中不能持久化的問題。
可以和Sentinel配合使用的數(shù)據(jù)源有很多種,比如ZooKeeper,Nacos,Apollo等等。這里介紹使用Nacos的方式。
首先要啟動(dòng)Nacos服務(wù)器,然后登錄到Nacos控制臺(tái),添加一個(gè)命名空間,添加配置。

接著我們就要改造Sentinel的源碼。因?yàn)楣倬W(wǎng)提供的Sentinel的jar是原始模式的,所以需要改造,所以我們需要拉取源碼下來改造一下,然后自己編譯jar包。
源碼地址:https://github.com/alibaba/Sentinel
拉取下來之后,導(dǎo)入到IDEA中,然后我們可以看到以下目錄結(jié)構(gòu)。

首先修改sentinel-dashboard的pom.xml文件:

第二步,把test目錄下的四個(gè)關(guān)于Nacos關(guān)聯(lián)的類,移到rule目錄下。

FlowRuleNacosProvider和FlowRuleNacosPublisher不需要怎么改造,本人不太喜歡名稱后綴,所以去掉了后面的后綴。

接著NacosConfig添加Nacos的地址配置。

最關(guān)鍵的是FlowControllerV1的改造,這是規(guī)則配置的增刪改查的一些接口。
把移動(dòng)到rule目錄下的兩個(gè)服務(wù),添加到FlowControllerV1類中。
@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
添加私有方法publishRules(),用于推送配置:
private void publishRules(/*@NonNull*/ String app) throws Exception {
List<FlowRuleEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app, rules);
}
修改apiQueryMachineRules()方法。

修改apiAddFlowRule()方法。

修改apiUpdateFlowRule()方法。

修改apiDeleteFlowRule()方法。

Sentinel控制臺(tái)的項(xiàng)目就改造完成了,用于生產(chǎn)環(huán)境就編譯成jar包運(yùn)行,如果是學(xué)習(xí)可以直接在IDEA運(yùn)行。
我們?cè)谇懊鎰?chuàng)建的HelloWord工程的pom.xml文件加上依賴。
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.8.1</version>
</dependency>
然后在application.yml文件加上以下配置:
spring:
cloud:
sentinel:
datasource:
flow:
nacos:
server-addr: localhost:8848
namespace: 05f447bc-8a0b-4686-9c34-344d7206ea94
dataId: springmvc-sentinel-flow-rules
groupId: SENTINEL_GROUP
# 規(guī)則類型,取值見:
# org.springframework.cloud.alibaba.sentinel.datasource.RuleType
rule-type: flow
data-type: json
application:
name: springmvc-sentinel-flow-rules
以上就完成了全部的配置和改造,啟動(dòng)Sentinel控制臺(tái),還有Java應(yīng)用。
打開Nacos控制臺(tái),我們添加限流配置如下:

配置內(nèi)容如下:
[{"app":"springmvc-sentinel-flow-rules","clusterConfig":{"acquireRefuseStrategy":0,"clientOfflineTime":2000,"fallbackToLocalWhenFail":true,"resourceTimeout":2000,"resourceTimeoutStrategy":0,"sampleCount":10,"strategy":0,"thresholdType":0,"windowIntervalMs":1000},"clusterMode":false,"controlBehavior":0,"count":1.0,"grade":1,"limitApp":"default","maxQueueingTimeMs":500,"resource":"userList","strategy":0,"warmUpPeriodSec":10},{"app":"springmvc-sentinel-flow-rules","clusterConfig":{"acquireRefuseStrategy":0,"clientOfflineTime":2000,"fallbackToLocalWhenFail":true,"resourceTimeout":2000,"resourceTimeoutStrategy":0,"sampleCount":10,"strategy":0,"thresholdType":0,"windowIntervalMs":1000},"clusterMode":false,"controlBehavior":0,"count":3.0,"grade":1,"limitApp":"default","maxQueueingTimeMs":500,"resource":"queryUserByUserName","strategy":0,"warmUpPeriodSec":10}]
然后我們打開Sentinel控制臺(tái),能看到配置,證明Nacos的配置推送成功了。

我們嘗試調(diào)用Java應(yīng)用的接口,測(cè)試是否生效。

可以看到限流是生效的,再看看Sentinel監(jiān)控的QPS情況。

從QPS監(jiān)控的情況看,最高的QPS只有3,其他請(qǐng)求都被拒絕了,證明限流配置是實(shí)時(shí)生效的。

配置信息也被持久化到Nacos相關(guān)的配置表中。
這時(shí)候,再回頭看Sentinel官網(wǎng)上關(guān)于推模式的架構(gòu)圖就比較清楚了。

總結(jié)
本篇文章主要介紹了Sentinel的基本用法,還有動(dòng)態(tài)規(guī)則的兩種方式,除此之外當(dāng)然還有許多功能,這里由于篇幅問題就不一一介紹了,有興趣的朋友可以自己探索一下。我個(gè)人覺得Sentinel是一個(gè)非常優(yōu)秀的組件,比原來用的Hystrix的確有著非常大的改進(jìn),值得推薦。
我們看到官網(wǎng)上登記的企業(yè)列表,也有很多知名企業(yè)在使用,相信以后Sentinel會(huì)越來越好。

這篇文章就講到這里了,感謝大家的閱讀,希望看完大家能有所收獲!
覺得有用就點(diǎn)個(gè)贊吧,你的點(diǎn)贊是我創(chuàng)作的最大動(dòng)力~
我是一個(gè)努力讓大家記住的程序員。我們下期再見!!!
能力有限,如果有什么錯(cuò)誤或者不當(dāng)之處,請(qǐng)大家批評(píng)指正,一起學(xué)習(xí)交流!
