閱讀本文大概需要20分鐘,但是還是要動手實(shí)驗(yàn)的哈,實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)。感覺博主整理的不錯的可以給個關(guān)注,本號后續(xù)陸續(xù)推出干貨
流量控制&熔斷降級產(chǎn)品對比
| Sentinel | Hystrix | Resilience4j | |
|---|---|---|---|
| 隔離策略 | 信號量隔離(并發(fā)線程數(shù)隔離) | 線程池隔離/信號量隔離 | 信號量隔離 |
| 熔斷降級策略 | 基于響應(yīng)時間、異常比率、異常數(shù) | 基于異常比率 | 基于異常比率、響應(yīng)時間 |
| 實(shí)時統(tǒng)計實(shí)現(xiàn) | 滑動窗口 | 滑動窗口 | Ring Bit Bufffer |
| 動態(tài)規(guī)則配置 | 支持多種數(shù)據(jù)源 | 支持多種數(shù)據(jù)源 | 有限支持 |
| 擴(kuò)展性 | 多個擴(kuò)展點(diǎn) | 插件的形式 | 接口的形式 |
| 基于注解的支持 | 支持 | 支持 | 支持 |
| 限流 | 基于QPS,支持基于調(diào)用關(guān)系的限流 | 有限的支持 | Rate Limiter |
| 流量整形 | 支持預(yù)熱模式、勻速器模式、預(yù)熱派對模式 | 不支持 | 簡單的Rate Limiter |
| 系統(tǒng)自適應(yīng)保護(hù) | 支持 | 不支持 | 不支持 |
| 控制臺 | 提供開箱即用的控制臺、可配置規(guī)則、查看秒級監(jiān)控、機(jī)器發(fā)現(xiàn) | 簡單的監(jiān)控查看 |
Sentinel 介紹
Sentinel 概述
Sentinel是阿里巴巴出品的面向分布式服務(wù)架構(gòu)的輕量級流量控制組件,主要以流量為切入點(diǎn),從限流、流量整形、熔斷降級、系統(tǒng)負(fù)載保護(hù)等多個維度來保障微服務(wù)的穩(wěn)定性
Sentinel 組成
- 核心庫:主要是指Java客戶端,不依賴任何框架、庫,能夠運(yùn)行與java7及以上的版本運(yùn)行時環(huán)境,同時對Dubbo、Spring Cloud等框架也有較好的支持
- 控制臺:控制臺主要負(fù)責(zé)管理推送規(guī)則、監(jiān)控、集群限流分配管理、機(jī)器發(fā)現(xiàn)等
Sentinel 特性

Sentinel 相關(guān)概念
資源
資源是Sentinel的關(guān)鍵概念。它可以是Java應(yīng)用程序中的任何內(nèi)容,例如,由應(yīng)用程序提供的服務(wù),或由應(yīng)用程序調(diào)用的其它應(yīng)用提供的服務(wù),甚至可以是一段代碼。只要通過Sentinel API定義的代碼,就是資源、能夠被Sentinel 保護(hù)起來。大部分情況下,可以使用方法簽名,URL,甚至服務(wù)名稱作為資源名來標(biāo)示資源
規(guī)則
規(guī)則指的是圍繞資源的實(shí)時狀態(tài)設(shè)定的規(guī)則,可以包括流量控制規(guī)則、熔斷降級規(guī)則以及系統(tǒng)保護(hù)規(guī)則。所有規(guī)則可以動態(tài)實(shí)時調(diào)整
Sentinel 優(yōu)勢
- 友好的控制面板
- 支持實(shí)時監(jiān)控
- 支持多種限流、支持QPS限流,線程數(shù)限流以及多種限流策略
- 支持多種降級模式、支持按平均返回時間降級,按多種異常數(shù)降級、按異常比率降級等
- 方便擴(kuò)展開發(fā),支持SPI模式對chain進(jìn)行擴(kuò)展
- 支持鏈路的關(guān)聯(lián)、可以實(shí)現(xiàn)按照鏈路統(tǒng)計限流,系統(tǒng)保護(hù),熱門資源保護(hù)等
SpringBoot+Sentinel
SpringBoot 環(huán)境信息
- SpringBoot 2.1.4.RELEASE
- JDK8
- Sentinel 1.7.2
內(nèi)置加載限流規(guī)則
-
pom加入sentinel依賴
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-core</artifactId> <version>1.7.2</version> </dependency> -
創(chuàng)建TestController
@RestController public class TestController { @GetMapping("/hello") public String hello(){ // 限流的資源名稱 try (Entry entry = SphU.entry("hello")){ return "hello sentinel"; }catch (BlockException e){ return "系統(tǒng)繁忙,請稍后"; } } @PostConstruct public void initFlowRules(){ List<FlowRule> list = new LinkedList<>(); FlowRule rule = new FlowRule(); // 限流資源名稱 rule.setResource("hello"); // 限流策略 rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 限流數(shù)量定義QPS每秒能通過的請求個數(shù) rule.setCount(2); list.add(rule); // 加載限流規(guī)則 FlowRuleManager.loadRules(list); } } 此時啟動應(yīng)用,訪問資源hello,每秒慢速點(diǎn)擊訪問可以正常訪問,如果快速點(diǎn)擊出現(xiàn)系統(tǒng)繁忙,請稍后

通過上面我們也能看到限流規(guī)則是在代碼中寫好的, 如果后續(xù)要修改的話,需要重新編譯非常的麻煩,現(xiàn)在Sentinel提供了一個控制臺,通過控制臺我們就能動態(tài)的修改限流規(guī)則,現(xiàn)在我們看下怎么使用Sentinel控制臺來實(shí)現(xiàn)限流策略
Sentinel 控制臺啟動
-
啟動
java -Dserver.port=8850 -jar sentinel-dashboard-1.8.4.jar 瀏覽器訪問 localhost:8050 賬號密碼默認(rèn)sentinel sentinel
SpringBoot應(yīng)用與Sentinel控制臺綁定
-
pom加入依賴
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-transport-simple-http</artifactId> <version>1.7.2</version> </dependency> -
JVM啟動時添加參數(shù)
-Dcsp.sentinel.dashboard.server=localhost:8850 -Dproject.name=SentinelQuickStartDemo -
重啟應(yīng)用并通過瀏覽器訪問 /hello接口幾次,查看控制臺中實(shí)時監(jiān)控效果
-
動態(tài)設(shè)置限流規(guī)則
- 首先取消代碼中的規(guī)則設(shè)置,注釋掉規(guī)則代碼

- 打開控制臺設(shè)置限流規(guī)則



- 訪問應(yīng)用接口,查看限流規(guī)則是否生效

Sentinel 定義資源的方式
Sentinel除了基本的定義資源的方式外,還有其它的定義資源的方式,具體如下:
- 拋出異常的方式定義資源
- 返回布爾值的方式定義資源
- 異步調(diào)用支持
- 注解方式調(diào)用支持
- 主流框架的默認(rèn)適配
拋出異常的方式定義資源
Sentinel中的SphU包含try-catch風(fēng)格的api。用這種方式,當(dāng)資源發(fā)生限流之后會拋出BlockException。這個時候可以捕捉異常,進(jìn)行限流之后的邏輯處理,而我們在上面就使用了這種方式進(jìn)行定義資源,關(guān)鍵代碼如下:
// 使用限流規(guī)則監(jiān)控保護(hù)資源
try (Entry entry = SphU.entry("hello")){
// 被保護(hù)的資源
return "hello sentinel";
}catch (BlockException e){
// 被限流或者降級的處理
return "系統(tǒng)繁忙,請稍后";
}
返回布爾值的方式定義資源
-
定義資源保護(hù)訪問
@RestController public class TestBooleanController { @GetMapping("/boolean") public boolean hello(){ if (SphO.entry("Sentinel_Boolean")){ try { System.out.println("Hello Sentinel"); return true; }finally { SphO.exit(); } }else{ // 限流降級的處理 System.out.println("系統(tǒng)繁忙,請稍后"); return false; } } }
- 新增限流規(guī)則

- 查看訪問結(jié)果

異步調(diào)用支持方式
-
開啟異步支持
// @EnableAsync 開啟異步支持 @EnableAsync @SpringBootApplication public class SentinelApplication { public static void main(String[] args) { SpringApplication.run(SentinelApplication.class, args); } } -
添加異步訪問方法
新建AcyncService方法
@Service public class AsyncService { @Async public void hello(){ System.out.println("異步開始======"); try { Thread.sleep(5000); }catch (InterruptedException e){ e.printStackTrace(); } System.out.println("異步結(jié)束======"); } }
-
添加異步訪問資源
@RestController public class TestAsyncController { @Autowired AsyncService asyncService; @GetMapping("/async") public void hello(){ AsyncEntry asyncEntry = null; try { asyncEntry = SphU.asyncEntry("Sentinel_Async"); asyncService.hello(); }catch (BlockException e){ System.out.println("系統(tǒng)繁忙,請稍后"); }finally { if (asyncEntry != null ){ asyncEntry.exit(); } } } }
-
添加限流規(guī)則
- 查看訪問效果

注解方式調(diào)用支持
-
添加注解支持的依賴
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-annotation-aspectj</artifactId> <version>1.7.2</version> </dependency>
-
創(chuàng)建Aspect配置類
@Configuration public class AspectConfig { @Bean public SentinelResourceAspect sentinelResourceAspect(){ return new SentinelResourceAspect(); } }
-
創(chuàng)建限流訪問資源代碼
@RestController public class TestAnnController { @Autowired AsyncService asyncService; @SentinelResource(value = "Sentinel_Ann",blockHandler = "exceptionHandler") @GetMapping("/ann") public String hello(){ return "Hello Sentinel"; } public void exceptionHandler(BlockException e){ e.printStackTrace(); System.out.println("系統(tǒng)繁忙,請稍后"); } }
主流框架的默認(rèn)適配
為了減少開發(fā)的復(fù)雜程度,對大部分的主流框架,例如Web Servlet,Dubbo、Spring Cloud、gRPC、Spring WebFlx、Reactor等都做了適配,只需要引入對應(yīng)的依賴就可以方便的整合Sentinel
SpringCloud+Sentinel
下面是整理本文時閱讀的一些資料匯總,有興趣的可以去看看

版本參考地址
SpringCloud Alibaba 版本對應(yīng)關(guān)系
SpringCloud版本詳細(xì)對應(yīng)關(guān)系
步驟
-
springcloud 版本
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.1.2.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
-
pom 加入sentinel依賴
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.1.0.RELEASE</version> </dependency>
-
創(chuàng)建限流資源代碼
@RestController public class TestController { @SentinelResource(value = "Sentinel_SpringCloud",blockHandler = "exceptionHandler") @GetMapping("/ann") public String hello(){ return "hello sentinel"; } public String exceptionHandler(BlockException e){ e.printStackTrace(); return "系統(tǒng)繁忙,請稍后"; } }
-
配置項目鏈接控制臺
spring.application.name=SpringCloudSentinel spring.cloud.sentinel.transport.dashboard=localhost:8850 -
創(chuàng)建限流規(guī)則
Sentinel+Feign
-
引入feign+sentinel的依賴
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.1.0.RELEASE</version> <exclusions> <exclusion> <groupId>io.github.openfeign</groupId> <artifactId>feign-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-core</artifactId> <version>10.1.0</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> -
定義服務(wù)提供類,ServiceProvider 中修改
@EnableDiscoveryClient @SpringBootApplication public class ServerProviderApplication { public static void main(String[] args) { SpringApplication.run(ServerProviderApplication.class, args); } @Slf4j @RestController static class TestController { @GetMapping("/hello/{str}") public String hello(@PathVariable String str) { log.info("invoked name = " + str); return "hello " + str; } @GetMapping("/test") public String test() { return "hello sentinel"; } } } -
增加feign客戶端的支持
@SpringBootApplication // 開啟feign-client @EnableFeignClients public class SentinelApplication { public static void main(String[] args) { SpringApplication.run(SentinelApplication.class, args); } } -
定義遠(yuǎn)程調(diào)用接口
@FeignClient(value = "alibaba-nacos-discovery-server",fallback = FallBackService.class) public interface FeignAgent { @GetMapping("/test") String hello(); }
-
定義回調(diào)降級類
@Component public class FallBackService implements FeignAgent { @Override public String hello() { return "系統(tǒng)繁忙,請稍后"; } } -
配置項目鏈接sentinel控制臺,開始sentinel對feign的支持
spring.application.name=SpringCloudSentinel spring.cloud.sentinel.transport.dashboard=localhost:8850 # feign-sentinel 支持 feign.sentinel.enabled=true 啟動注冊中心nacos,服務(wù)提供者serviceProvider和sentinel客戶端
-
定義限流規(guī)則,Sentinel和Feign整合時,限流規(guī)則的編寫形式為:
http請求方式:協(xié)議://服務(wù)名/請求路徑跟參數(shù) 例:GET:http://alibaba-nacos-discovery-server/test

Sentinel+SpringCloud Gateway
-
引入依賴
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.2</version> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId> <version>2.1.0.RELEASE</version> </dependency> -
配置gateway信息,鏈接Sentinel控制臺
spring: application: name: SpringCloudGateWay cloud: gateway: routes: # id: sentinel-feign-gateway 限流時route id使用這個 - id: sentinel-feign-gateway uri: lb://SpringCloudSentinel:8002 predicates: # Path=/feign/** 自定義API維度限流使用 - Path=/feign/** nacos: discovery: server-addr: 127.0.0.1:8848 sentinel: transport: dashboard: 127.0.0.1:8850 server: port: 8003 -
配置限流時返回內(nèi)容
@Component public class GatewayConfiguration { @PostConstruct public void doInit(){ GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() { @Override public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) { return ServerResponse.status(200).syncBody("系統(tǒng)繁忙,請稍后"); } }); } } -
啟用服務(wù)發(fā)現(xiàn)
@EnableDiscoveryClient @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
限流規(guī)則配置
- route id

- 自定義API維度

流量控制實(shí)現(xiàn)
Sentinel的所有規(guī)則都可以在內(nèi)存態(tài)中動態(tài)的查詢及修改,修改之后立即生效。同時Sentinel也提供API,選擇定制自己的規(guī)則策略
Sentinel主要支持以下幾種規(guī)則
- 流量控制規(guī)則
- 熔斷降級規(guī)則
- 系統(tǒng)保護(hù)規(guī)則
- 來源訪問控制規(guī)則
- 動態(tài)規(guī)則擴(kuò)展
流量控制規(guī)則實(shí)現(xiàn)
流量控制(flow control),其原理是監(jiān)控應(yīng)用流量的QPS或并發(fā)線程數(shù)等指標(biāo),當(dāng)達(dá)到制定的閾值時對流量進(jìn)行控制,以避免被瞬時的流量高峰沖垮,從而保障應(yīng)用的高可用性
流量控制主要有兩種方式
并發(fā)線程數(shù):并發(fā)線程數(shù)限流用于保護(hù)業(yè)務(wù)線程數(shù)不被耗盡
QPS:當(dāng)QPS超過某個閾值的時候,則采取措施進(jìn)行流量控制
一條限流規(guī)則主要由下面幾個元素組成,我們可以組成這些元素來實(shí)現(xiàn)不同的限流效果:
resource:資源名,即限流的對象
count:限流閾值
grade:限流閾值類型(QPS或并發(fā)線程數(shù))
limitApp:流控針對的調(diào)用來源,若為default則不區(qū)分調(diào)用來源
strategy:調(diào)用關(guān)系限流策略
-
controBehavior:流量控制效果(直接拒絕,Warm Up,勻速排隊)
- 直接拒絕(RuleConstant.CONTROL_BRHAVIOR_DEFAULT)方式是默認(rèn)的流量控制方式,當(dāng)QPS超過任意規(guī)則的閾值后,新的請求被立即拒絕,拒絕方式為拋出
FlowException.這種方式適用與對系統(tǒng)處理能力確切已知的請求下,比如通過壓測確定了系統(tǒng)的準(zhǔn)確水位時 - Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即預(yù)熱,冷啟動方式,當(dāng)系統(tǒng)長期處于低水位的情況下,當(dāng)流量突然增加時,直接把系統(tǒng)拉升到高水位可能瞬間把系統(tǒng)壓垮。通過“冷啟動”,讓通過的流量緩慢增加,在一定時間內(nèi)逐漸增加到閾值上限,給冷系統(tǒng)一個預(yù)熱的時間。避免冷系統(tǒng)被壓垮
- 排隊等待(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式會嚴(yán)格控制請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應(yīng)的是漏桶算法
同一個資源可以同時由多個限流規(guī)則,檢查規(guī)則時會依次檢查
- 直接拒絕(RuleConstant.CONTROL_BRHAVIOR_DEFAULT)方式是默認(rèn)的流量控制方式,當(dāng)QPS超過任意規(guī)則的閾值后,新的請求被立即拒絕,拒絕方式為拋出
熔斷降級
熔斷降級會在調(diào)用鏈路中某個資源出現(xiàn)不穩(wěn)定狀態(tài)時(例如調(diào)用超時或異常比例升高),對這個資源的調(diào)用進(jìn)行限制,讓請求快速失敗,避免影響到其它的資源而導(dǎo)致級聯(lián)錯誤。當(dāng)資源被降級后,在接下來的降級時間窗口之內(nèi),對該資源的調(diào)用都自行熔斷(默認(rèn)行為是拋出DegradeException)
| Field | 說明 | 默認(rèn)值 |
|---|---|---|
| resource | 資源名,即限流規(guī)則的對象 | |
| count | 閾值 | |
| grade | 熔斷策略,支持秒級RT/秒級異常比例/分鐘級異常數(shù) | 秒級平均RT |
| timeWindow | 降級的時間,單位為s | |
| reSlowRequestAmount | RT模式下1秒內(nèi)連續(xù)多少個請求的平均RT超出閾值方可觸發(fā)熔斷(1.7.0引入) | 5 |
| minRequestAmount | 異常熔斷的觸發(fā)最小請求數(shù),請求數(shù)小于該值時及時異常比率超出閾值也不會熔斷(1.7.0引入) | 5 |
同一個資源可以有多個降級規(guī)則
熔斷策略詳解
- 平均響應(yīng)時間(DEGRADE_GRADE_RT):當(dāng)1s內(nèi)連續(xù)進(jìn)入N個請求,對應(yīng)時刻的平均響應(yīng)時間(秒級)均超過閾值(count,以ms為單位),那么接下來的時間(DegradeRule 中的timeWindow,以s為單位)之內(nèi),對這個方法的調(diào)用都會自動熔斷
- 異常比例(DEGRADE_GRADE_EXCEPTION_RATIO):當(dāng)資源的每秒請求量>=N(可配置),并且每秒異常總數(shù)占通過量的比值超過閾值(DegradeRule中的count)之后,資源進(jìn)入降級狀態(tài),即在接下的時間(DegradeRule 中的timeWindow,以s為單位)之內(nèi),對這個方法調(diào)用都會自動的返回。異常比率的閾值范圍時[0.0,1.0],代表0%-100%
- 異常數(shù)(DEGRADE_GRADE_EXCEPTION_COUNT):當(dāng)資源近一分鐘的異常數(shù)目超過閾值之后就會進(jìn)行熔斷。注意由于統(tǒng)計時間時分鐘級別的,若timeWindow小于60s,則結(jié)束熔斷狀態(tài)后仍可能再進(jìn)入熔斷狀態(tài)
熔斷降級設(shè)計理念
在限制的手段上,Sentinel和Hystrix采取完全不一樣的方法
Hystrix通過線程池隔離的方式,來對依賴(在Sentinel的概念中對應(yīng)資源)進(jìn)行了隔離,這樣做的好處是資源和資源之間做到了最徹底的隔離。缺點(diǎn)是除了增加了線程切換的成本(過多的線程池導(dǎo)致線程數(shù)目過多)還需要預(yù)先給各個資源做線程池大小的分配
Sentinel對這個問題采取了兩種手段
-
通過并發(fā)線程數(shù)進(jìn)行限制
和資源池隔離的方法不同,Sentinel通過限制資源并發(fā)線程的數(shù)量,來減少不穩(wěn)定資源對其它資源的影響。這樣不但沒有線程切換的損耗,也不需要您預(yù)先分配線程池的大小。當(dāng)某個資源出現(xiàn)不穩(wěn)定的情況下,例如響應(yīng)時間變長,對資源的直接影響就是會導(dǎo)致線程數(shù)的逐步累積,當(dāng)線程數(shù)在特定資源上堆積到一定的數(shù)量之后,對該資源的新請求就會被拒絕,堆積的線程完成任務(wù)后才開始繼續(xù)接收請求
-
通過響應(yīng)時間對資源進(jìn)行降級
除了對并發(fā)線程數(shù)進(jìn)行控制以外,Sentinel還可以通過響應(yīng)時間來快速降級不穩(wěn)定的資源。當(dāng)依賴的資源出現(xiàn)響應(yīng)時間過長后,所有對該資源的訪問都會被直接拒絕,直到過了指定的時間窗口之后才重新恢復(fù)
系統(tǒng)自適應(yīng)保護(hù)實(shí)現(xiàn)
Sentinel 系統(tǒng)自適應(yīng)限流從整體維度對應(yīng)用入口流量進(jìn)行控制,結(jié)合應(yīng)用的Load、CPU使用率、總體平均RT、入口QPS和并發(fā)線程數(shù)等幾個維度的監(jiān)控指標(biāo),通過自適應(yīng)的流控策略,讓系統(tǒng)的入口流量和系統(tǒng)的負(fù)載達(dá)到一個平衡,讓系統(tǒng)盡可能的保持最大吞吐量的同時保證系統(tǒng)整體的穩(wěn)定性
系統(tǒng)保護(hù)規(guī)則是應(yīng)用整體維度的,而不是資源維度的,并且僅對入口流量生效,入口流量指的是進(jìn)入應(yīng)用的流量(EntryType.IN),比如Web服務(wù)或者Dubbo服務(wù)端接收到的請求,都屬于入口流量
系統(tǒng)規(guī)則支持一下的模式
- Load自適應(yīng)(僅對Linux/Unix-like機(jī)器生效):系統(tǒng)的load1作為啟發(fā)指標(biāo),進(jìn)行自適應(yīng)系統(tǒng)保護(hù),當(dāng)系統(tǒng)load1超過設(shè)定的啟發(fā)值,且系統(tǒng)當(dāng)前的并發(fā)線程數(shù)超過估算的系統(tǒng)容量是才會觸發(fā)系統(tǒng)保護(hù)(BBR階段).系統(tǒng)容量由系統(tǒng)的
maxQps*minRt估算得出,設(shè)定參考值一般是CPU cores * 2.5 - CPU usage (1.5.0版本):當(dāng)系統(tǒng)CPU使用率超過閾值即出發(fā)系統(tǒng)保護(hù)(取值范圍0.0-1.0)比較靈敏
- 平均RT:當(dāng)單臺機(jī)器上所有入口流量的并發(fā)線程數(shù)達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)
- 并發(fā)線程數(shù):當(dāng)單臺機(jī)器上所有入口流量的并發(fā)線程數(shù)達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)
- 入口QPS:當(dāng)單臺機(jī)器上所有入口流量的QPS達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)
重要的屬性
| Field | 說明 | 默認(rèn)值 |
|---|---|---|
| highestSystemLoad | load1觸發(fā)值,用于觸發(fā)自適應(yīng)控制階段 | -1(不生效) |
| avgRt | 所有入口流量的平均響應(yīng)時間 | -1(不生效) |
| maxThread | 入口l巨量的最大并發(fā)數(shù) | -1(不生效) |
| qps | 所有入口資源的QPS | -1(不生效) |
| highestCpuUsage | 當(dāng)前系統(tǒng)的CPU使用率(0.0-1.0) | -1(不生效) |
代碼控制
@RestController
public class TestLoadController {
@SentinelResource(entryType = EntryType.IN)
@GetMapping("/rule")
public String hello(){
return "hello sentinel rule";
}
// @PostConstruct
// public void initDegradeRule(){
// List<SystemRule> rules = new LinkedList<>();
// SystemRule rule = new SystemRule();
// rule.setQps(2);
// rules.add(rule);
// SystemRuleManager.loadRules(rules);
// }
}
控制臺配置
系統(tǒng)設(shè)置
授權(quán)控制
很多時候,我們需要根據(jù)調(diào)用來源來判斷請求是否允許放行,這時候可以使用Sentinel的來源訪問控制(黑白名單控制)的功能,來源訪問控制根據(jù)資源的請求來源(origin)判斷資源是否通過,若配置白名單則只有請求來源位于白名單內(nèi)時才可通過;若配置黑名單則請求來源位于黑名單時不通過,其余的請求通過
重要屬性
- resource: 資源名,即限流規(guī)則的對象
- limitApp: 請求來源,對應(yīng)的黑名單/白名單,多個用“,"分割
- strategy:限制模式,AUTHORITY_WHITE為白名單模式,AYTHORITY_BLACK為黑名單模式,默認(rèn)為白名單模式
代碼配置
- 黑白名單配置
@RestController
public class WhiteBlackController {
@SentinelResource(value = "Sentinel_Rule",blockHandler = "exceptionHandler")
@GetMapping("/rule")
public String hello(){
return "hello sentinel rule";
}
public String exceptionHandler(BlockException e){
e.printStackTrace();
return "系統(tǒng)繁忙,請稍后";
}
@PostConstruct
public void initWhiteRules(){
List<AuthorityRule> rules = new LinkedList<>();
AuthorityRule rule = new AuthorityRule();
rule.setResource("Sentinel_Rule");
rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
rule.setLimitApp("192.168.168.168");
rules.add(rule);
AuthorityRuleManager.loadRules(rules);
}
@PostConstruct
public void initBlackRules(){
List<AuthorityRule> rules = new LinkedList<>();
AuthorityRule rule = new AuthorityRule();
rule.setResource("Sentinel_Rule");
rule.setStrategy(RuleConstant.AUTHORITY_BLACK);
rule.setLimitApp("127.0.0.1");
rules.add(rule);
AuthorityRuleManager.loadRules(rules);
}
}
-
獲取IP配置
@Component public class SentinelConfig { @PostConstruct public void init(){ WebCallbackManager.setRequestOriginParser(new RequestOriginParser() { @Override public String parseOrigin(HttpServletRequest httpServletRequest) { return httpServletRequest.getRemoteAddr(); } }); } }
動態(tài)規(guī)則設(shè)置
拉模式拓展
實(shí)現(xiàn)拉模式的數(shù)據(jù)源最簡單的方式是繼承AutoRefreshDataSource抽象類,然后實(shí)現(xiàn)readSource()方法,在該方法里從指定數(shù)據(jù)源讀取字符串格式的配置數(shù)據(jù)。
推模式拓展
實(shí)現(xiàn)推模式的數(shù)據(jù)源最簡單的方式是繼承 AbstractDataSource 抽象類,在其構(gòu)造方法中添加監(jiān)聽器,并實(shí)現(xiàn) readSource() 從指定數(shù)據(jù)源讀取字符串格式的配置數(shù)據(jù)。比如 基于 Nacos 的數(shù)據(jù)源。
推模式:使用Nacos配置規(guī)則
-
pom加入依賴
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <version>1.7.1</version> </dependency> -
動態(tài)配置規(guī)則
@Component public class SentinelDataSourceConfig { private static final String KEY = "TestResource"; // nacos server ip private static final String remoteAddress = "localhost:8848"; // nacos group private static final String groupId = "Sentinel_Demo"; // nacos dataId private static final String dataId = "com.alibaba.csp.sentinel.demo.flow.rule"; // if change to true, should be config NACOS_NAMESPACE_ID private static boolean isDemoNamespace = false; // fill your namespace id,if you want to use namespace. for example: 0f5c7314-4983-4022-ad5a-347de1d1057d,you can get it on nacos's console private static final String NACOS_NAMESPACE_ID = "${namespace}"; @PostConstruct private static void loadRules() { ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() { })); FlowRuleManager.register2Property(flowRuleDataSource.getProperty()); } private static void loadMyNamespaceRules() { Properties properties = new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, remoteAddress); properties.put(PropertyKeyConst.NAMESPACE, NACOS_NAMESPACE_ID); ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(properties, groupId, dataId, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() { })); FlowRuleManager.register2Property(flowRuleDataSource.getProperty()); } } -
發(fā)送nacos配置,或者手動創(chuàng)建
public static void main(String[] args) throws Exception { final String remoteAddress = "localhost:8848"; final String groupId = "Sentinel_Demo"; final String dataId = "com.alibaba.csp.sentinel.demo.flow.rule"; final String rule = "[\n" + " {\n" + " \"resource\": \"Sentinel_SpringCloud\",\n" + " \"controlBehavior\": 0,\n" + " \"count\": 5.0,\n" + " \"grade\": 1,\n" + " \"limitApp\": \"default\",\n" + " \"strategy\": 0\n" + " }\n" + "]"; ConfigService configService = NacosFactory.createConfigService(remoteAddress); System.out.println(configService.publishConfig(dataId, groupId, rule)); }
行了,到這就結(jié)束了,本來打算簡單整理一下,但是發(fā)現(xiàn)越整理越多,而且真的是沒有試驗(yàn)一切都是刷流氓,快去寫個demo體驗(yàn)下Sentinel的絲滑吧

本文由mdnice多平臺發(fā)布


