概述
目录
服务雪崩
1.服务雪崩效应
2.解决方案
Sentinel
1.Sentinel是什么
2.Sentinel和Hystrix的区别
3.Sentinel快速开始
3.1 初体验流量控制规则
3.2 注解方式定义资源
Sentinel控制台
控制台部署
客户端接入控制台
SpringCloudAlibaba整合Sentinel
流控规则
场景:
阈值类型
流控模式
流控效果
熔断降级规则
降级规则
熔断降级规则说明
熔断策略
Sentinel整合OpenFeign进行降级
热点参数流控
常用场景
实现原理
配合热点参数规则
系统保护规则
BlockException异常统一处理
规则持久化
push模式
基于Nacos配置中心控制台实现推送
Sentinel控制台规则同步到Nacos
服务雪崩
1.服务雪崩效应
因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程,就叫服务雪崩效应。
导致服务不可用的原因:
- 激增流量:激增流量导致系统CPU飙高,无法正常处理请求;激增流量打垮冷系统(数据库连接未创建,缓存未预热) ;消息投递速度过快,导致消息处理积压。
- 不稳定服务依赖:慢sql查询卡爆连接池;第三方服务不响应,卡满线程池;业务调用持续出现异常,产生大量的副作用。
- 。。。
在服务提供者不可用的时候,会出现大量重试的情况:用户重试,代码逻辑重试,这些重试最终导致进一步加大请求流量。所以归根结底导致雪崩效应的最根本原因是:大量请求线程同步等待造成的资源耗尽。当服务调用者使用同步调用时,会产生大量的等待线程占用系统资源。一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用的状态,于是服务雪崩效应产生了。
2.解决方案
常见的容错机制:
- 超时机制:在不做任何处理的情况下,服务提供者不可用会导致消费者请求线程强制等待,而造成系统资源耗尽。加入超时机制,一旦超时,就释放资源。由于释放资源速度较快,一定程度上可以抑制资源耗尽的问题。
- 服务限流:当达到一定的流量后,拒绝访问。
- 隔离:用户的请求将不在直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,则会进行降级处理,用户的请求不会被阻塞,至少可以看到一个执行结果(例如返回友好的提示信息),而不是无休止的等待或者看到系统崩溃。
- 信号隔离:信号隔离也可以用于限制并发访问,防止阻塞扩散,与线程隔离最大不同在于执行依赖代码的线程依然是请求线程(该线程需要通过信号申请,如果客户端是可信的且可以快速返回,可以使用信号隔离替换线程隔离,降低开销,信号量的大小可以动态调整,线程池大小不可以)
- 服务熔断
远程服务不稳定或网络抖动时暂时关闭,就叫服务熔断
实时监测应用,如果发现在一定时间内失败次数/失败率达到一定阈值,就跳闸,断路器打开,此时,请求直接返回,而不去调用原本调用的逻辑。跳闸一段时间后,断路器会进入半开状态,这是一个瞬间态,此时允许一次请求调用该调的逻辑,如果成功,则断路器关闭,应用正常调用;如果调用依然不成功,断路器继续回到打开状态,过段时间在进入半开状态尝试。通过跳闸,应用可以保护自己,而且避免浪费资源,而通过半开的设计,可实现应用的自我修复。
所以,同样的道理,当依赖的服务有大量超时时,再让新的请求去访问根本没有意义,只会无畏的消耗现有资源。比如我们设置了超时时间为1s,如果短时间内有大量请求在1s内都得不到响应,就意味着这个服务出现了异常,此时就没有必要再让其它的请求去访问这个依赖了,这个时候就应该使用断路器避免资源浪费。
服务降级
有服务熔断,必须要有服务降级。
所谓降级,就是当某个服务熔断后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值,例如:备用接口/缓存/mock数据。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看合适的业务场景。
Sentinel
1.Sentinel是什么
sentinel是alibaba开源的,面向分布式服务架构的高可用防护组件。
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel是面向分布式服务架构的流量控制组件,主要以流量切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。
官方地址:https://github.com/alibaba/Sentinel/wiki
Sentinel具有以下特征:
- 丰富的应用场景:Sentinel承接了alibaba近10年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel同时提供实时的监控功能。你可以在控制台中看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况
- 广泛的开源生态:Sentinel提供开箱即用的与其它开源框架的整合模块,例如SpringCloud、Dubbo的整合。你只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel
- 完善的SPI扩展点:Sentinel提供简单易用、完善的SPI扩展点。你可以通过实现扩展点,快速的定制逻辑。例如定制规则管理,适配数据源等。
阿里云提供了企业级的Sentinel服务,应用高可用服务AHAS。
2.Sentinel和Hystrix的区别
sentinel | hystrix | |
---|---|---|
隔离策略 | 信号量隔离 | 线程池隔离/信号量隔离 |
熔断降级策略 | 基于响应时间或失败比率 | 基于失败比率 |
实时指标实现 | 滑动窗口 | 滑动窗口 |
规则配置 | 支持多种数据源 | 支持多种数据源 |
扩展性 | 多个扩展点 | 插件的形式 |
基于注解的支持 | 支持 | 支持 |
限流 | 基于QPS,支持基于调用关系的限流 | 有限的支持 |
流量整形 | 支持慢启动、匀速器模式 | 不支持 |
系统负载保护 | 支持 | 不支持 |
控制台 | 开箱即用,可配置规则、查看秒级监控、机器发现等 | 不完善 |
常见框架的适配 | Servlet、SpringCloud、Dubbo、gRPC等 | Servlet、SpringCloud Netflix |
3.Sentinel快速开始
3.1 初体验流量控制规则
1.引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zjb</groupId>
<artifactId>sentinel-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sentinel-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Sentinel核心库-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.定义资源
@RequestMapping("/hello")
public String hello() {
Entry entry = null;
try {
//定义资源
// 资源名可使用任意有业务语义的字符串,注意数目不能太多(超过 1K),超出几千请作为参数传入而不要直接作为资源名
entry = SphU.entry(RESOURCE_NAME);
// 被保护的业务逻辑
String str = "hello sentinel";
log.info("===" + str + "===");
return str;
} catch (BlockException ex) {
// 资源访问阻止,被限流或被降级
// 进行相应的处理操作
log.info("block");
return "被流控了";
} catch (Exception ex) {
// 若需要配置降级规则,需要通过这种方式记录业务异常
Tracer.traceEntry(ex, entry);
} finally {
// 务必保证 exit,务必保证每个 entry 与 exit 配对
if (entry != null) {
entry.exit();
}
}
return null;
}
3.定义流控规则
/**
* 设置流控规则
*
* @PostConstruct :Spring的注解,当加载spring容器时,会自动初始化加了该注解的方法
*/
@PostConstruct
private static void initFlowQpsRule(){
//规则集合
List<FlowRule> rules = new ArrayList<>();
//流控规则
FlowRule rule = new FlowRule();
//设置受保护的资源
rule.setResource(RESOURCE_NAME);
//设置流控规则的QPS
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//设置受保护的资源阈值
rule.setCount(1);
//流控针对的调用来源 ,default,代表不区分调用来源
rule.setLimitApp("default");
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
4.验证测试
3.2 注解方式定义资源
Sentinel 支持通过 @SentinelResource
注解定义资源并配置 blockHandler
和 fallback
函数来进行限流之后的处理。
@SentinelResource
注解包含以下属性:
value
:资源名称,必需项(不能为空)entryType
:entry 类型,可选项(默认为EntryType.OUT
)blockHandler
/blockHandlerClass
:blockHandler
对应处理BlockException
的函数名称,可选项。blockHandler 函数访问范围需要是public
,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException
。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定blockHandlerClass
为对应的类的Class
对象,注意对应的函数必需为 static 函数,否则无法解析。fallback
/fallbackClass
:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore
里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:- 返回值类型必须与原函数返回值类型一致;
- 方法参数列表需要和原函数一致,或者可以额外多一个
Throwable
类型的参数用于接收对应的异常。 - fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定
fallbackClass
为对应的类的Class
对象,注意对应的函数必需为 static 函数,否则无法解析。
defaultFallback
(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore
里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:- 返回值类型必须与原函数返回值类型一致;
- 方法参数列表需要为空,或者可以额外多一个
Throwable
类型的参数用于接收对应的异常。 - defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定
fallbackClass
为对应的类的Class
对象,注意对应的函数必需为 static 函数,否则无法解析。
exceptionsToIgnore
(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。-
1.8.0 版本开始,
defaultFallback
支持在类级别进行配置。注:1.6.0 之前的版本 fallback 函数只针对降级异常(
DegradeException
)进行处理,不能针对业务异常进行处理。特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出
BlockException
时只会进入blockHandler
处理逻辑。若未配置blockHandler
、fallback
和defaultFallback
,则被限流降级时会将BlockException
直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层UndeclaredThrowableException
)。
1.引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.2</version>
</dependency>
2.配置bean
若您是通过 SpringCloudAlibaba 接入的 Sentinel,则无需额外进行配置即可使用 @SentinelResource
注解。
若您的应用使用了 Spring AOP(无论是 Spring Boot 还是传统 Spring 应用),您需要通过配置的方式将 SentinelResourceAspect
注册为一个 Spring Bean。
@Configuration
public class SentinelAspectConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
3.定义接口并使用@SentinelResource注解
@RequestMapping("/hello2")
@SentinelResource(value = HELLO2_RESOURCE_NAME,blockHandler = "exceptionHandler")
public String hello2(String str) {
return String.format("Hello %d", str);
}
/**
* Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
* @param str
* @param e
* @return
*/
public String exceptionHandler(String str,BlockException e) {
e.printStackTrace();
return String.format("被限流了 %d", str);
}
Sentinel控制台
控制台部署
1.下载控制台 jar 包
下载地址:https://github.com/alibaba/Sentinel/releases
2. 启动
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.2.jar
为了方便快捷启动可以在桌面创建start.bat文件
java -Dserver.port=8080 -jar D:SpringCloudAlibaba-2.2.7sentinel-dashboard-1.8.2.jar
pause
访问http://localhost:8080/#/login , 账号密码:sentinel/sentinel
客户端接入控制台
1.引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.2</version>
</dependency>
2. 配置启动参数
启动时加入 JVM 参数 -Dcsp.sentinel.dashboard.server=consoleIp:port
指定控制台地址和端 口。
SpringCloudAlibaba整合Sentinel
1.引入依赖
<!--添加Sentinel启动器-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.配置yml文件
server:
port: 8010
#应用名称
spring:
application:
name: order-service
cloud:
sentinel:
transport:
#sentinel控制台地址
dashboard: 127.0.0.1:8080
流控规则
流量控制(flow control) ,其原理是监控应用流量的QPS或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
FlowRule RT(响应时间) 1/0.2s = 5
场景:
- 应对洪峰流量:秒杀,大促,下单,订单回流处理
- 消息型场景:削峰填谷,冷热启动
- 付费系统:根据使用流量付费
- API Gateway:精准控制API流量
- 任何应用:探测应用中运行的慢程序块,进行限制
通常在服务提供端进行流控,针对不同调用来源进行流控。
阈值类型
QPS(Query Per Second):每秒请求数,就是说服务器在一秒的时间内处理了多少请求。
并发线程数
并发数控制用于保护业务线程池不被慢调用耗尽。例如:当应用所依赖的下游应用由于某种原因导致服务不稳定、响应延迟增加,对于调用者来说,意味着吞吐量下降和更多的线程数占用,极端情况下甚至导致线程池耗尽。为应对太多线程占用的情况,业内有使用隔离的方案,比如通过不同业务逻辑使用不同线程池来隔离业务自身之间的资源争抢(线程池隔离)。这种隔离方案虽然隔离性比较好,但是代价就是线程数目太多,线程上下文切换的overhead比较大,特别是对低延时的调用有比较大的影响。Sentinel并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目),如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。并发数控制通常在调用端进行配置。
流控模式
基于调用关系的流量控制。调用关系包括调用方、被调用方;一个方法可能会调用其它方法,形成一个调用链路的层次关系。
关联
当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便有了关联。比如对数据库同一个字段的读操作和写操作存在争抢,读的速度过高会影响写的速度,写的速度过高会影响读的速度。如果放任读写操作争抢资源,则争抢本身带来的开销会降低整体的吞吐量。可使用关联限流来避免具有关联关系的资源之间过度的争抢,举例来说,read_db和write_db这两个资源分别代表数据库读写,我们可以给read_db设置限流规则来达到写优先的目的:设置strategy为RuleConstant.STRATEGY_RELATE同时设置refResource为write_db。这样当写库操作过于频繁时,读数据的请求会被限流。
链路
根据调用链路入口限流。
注意:高版本直接使用该功能不生效,如何解决?
从1.6.3版本开始,Sentinel Web filter默认收敛所有URL的入口context,因此链路限流不生效。
1.7.0版本开始,官方在CommonFilter引入了WEB_CONTEXT_UNIFY参数,用于控制是否收敛context。将其配置为false即可根据不同的URL进行链路限流。
//默认将调用链路收敛
spring.cloud.sentinel.web-context-unify=false
此场景下因为使用的是@SentinelResource注解,作用在方法上,所以全局的统一异常处理是不生效的,只能在@SentinelResource注解中指定blockHandler处理BlockException。
总结:为了解决链路规则引入CommonFilter的方式,除了此处问题,还会导致更多的问题,不建议使用CommonFilter的方式。流控链路模式的问题等待官方后续修复,或者使用AHAS。
流控效果
快速失败
默认就是快速失败,当超过阈值时,直接就返回失败。
Warm Up(适用激增流量)
也就是预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过冷启动,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
冷加载因子:codeFactor默认是3,即请求QPS从 threshold/3 开始,经预热时长逐渐升至设定的QPS阈值。
排队等待(适用脉冲流量)
排队等待会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
这种方式主要用于处理间隔性突发的流量,例如消息队列。在某一秒有大量的请求到来,而接下来的几秒处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。
注:排队等待模式暂时不支持 QPS > 1000的场景。
熔断降级规则
降级规则
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。
熔断降级规则说明
熔断降级规则包含下面几个重要的属性:
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,即规则的作用对象 | |
grade | 熔断策略,支持慢调用比例、异常比例、异常数策略 | 慢调用比例 |
count | 慢调用比例模式下为慢调用临届RT(超出该值为慢调用);异常比例/异常数模式下为对应的阈值 | |
timeWindow | 熔断时长,单位为s | |
minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断 | 5 |
statIntervalMs | 统计时长(单位:ms),如60 * 1000 代表分钟级 | 1000ms |
slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效 |
熔断策略
慢调用比例(SLOW_REQUEST_RATIO)
选择以慢调用比例作为阈值,需要设置允许的慢调用RT(即最大响应时间),请求响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数大于设置的最小请求数,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN状态),若接下来的一个请求响应时间小于设置的慢调用RT则结束熔断,若大于设置的慢调用RT则会再次被熔断。
异常比例(ERROR_RATIO)
当单位统计时长内请求数大于设置的最小请求数,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态,若接下来的一个请求成功完成则结束熔断,否则会再次熔断。异常比例的阈值范围是0-1,代表0%-100%。
异常数(ERROR_COUNT)
当单位统计时长内的异常数超过阈值之后会自动进行熔断。经过熔断时长后会进入探测状态,若接下来的一个请求成功完成则结束熔断,否则会再次熔断。
注意:异常降级仅针对业务异常,对Sentinel限流降级本身的异常(BlockException)不生效。
Sentinel整合OpenFeign进行降级
1.引入依赖
<!--Nacos Client-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--添加openfeign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--添加Sentinel启动器-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.开启OpenFeign对Sentinel的支持
feign:
sentinel:
# 开启OpenFeign对Sentinel的支持
enabled: true
3.添加服务降级的处理类
package com.zjb.order.feign;
import com.zjb.order.config.FeignConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* name: 指定调用rest接口所对应的服务名
* path:指定调用rest接口所在的Controller指定的RequestMapping
*/
@FeignClient(name = "stock-service",path = "/stock",configuration = FeignConfig.class,fallback = StockFeignFallbackServiceImpl.class)
public interface StockFeignSerivce {
/**
* 声明需要调用的rest接口对应的方法
* @return
*/
@RequestMapping("/reduct")
String reduct();
}
package com.zjb.order.feign;
import org.springframework.stereotype.Service;
@Service
public class StockFeignFallbackServiceImpl implements StockFeignSerivce {
public String reduct() {
return "服务降级了";
}
}
这样就整合完了。
热点参数流控
何为热点 ?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的数据,并对其进行限制。
常用场景
- 热点商品访问、操作控制
- 用户/IP防刷
实现原理
热点淘汰策略(LRU)+ Token Bucket流控
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
注意:
1.热点规则需要使用@SentinelResource注解,否则不生效。
2.参数必须是7中基本数据类型才会生效。
配合热点参数规则
注意:资源名必须是@SentinelResource注解配置的资源名,热点规则依赖于注解。
系统保护规则
Sentinel系统自适应限流从整体纬度对应用入口流量进行控制,结合应用的Load,CPU使用率,总体平均RT,入口QPS和并发线程数等几个纬度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
- Load自适应(仅对Linux、Unix-like机器生效):系统的load1作为启动指标,进行自适应系统保护。当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR阶段)。系统容量由系统的maxQPS * minRT估算得出。设定参考值一般是CPU cores * 2.5。
- CPU usage:当系统cpu使用率超过阈值即触发系统保护(取值范围0.0-1.0),比较灵敏。
- 平均RT:当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位是毫秒。
- 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值时即触发系统保护。
- 入口QPS:当单台机器上所有入口流量的QPS达到阈值时即触发系统保护。
BlockException异常统一处理
springwebmvc接口资源限流入口在HandlerInterceptor的实现类AbstractSentinelInterceptor的perHandler方法中,对异常的处理是BlockExceptionHandler的实现类 。
自定义BlockExceptionHandler的实现类统一处理BlockException。
package com.zjb.order.exception;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zjb.order.domain.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* BlockException异常统一处理
* 如果需要特殊的异常处理,建议仍使用@SentinelResource注解
*/
@Component
public class SentinelBlockException implements BlockExceptionHandler {
Logger log = LoggerFactory.getLogger(this.getClass());
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse response, BlockException e) throws Exception {
//getRule():获取资源信息,规则的详细信息
log.info("BlockExceptionHandler BlockException:{}",e.getRule());
Result result = null;
if(e instanceof FlowException){
result = result.error("100","接口限流了");
}else if(e instanceof DegradeException){
result = result.error("101","服务降级了");
}else if(e instanceof AuthorityException){
result = result.error("102","授权规则不通过");
}else if(e instanceof SystemBlockException){
result = result.error("103","触发系统保护规则了");
}else if(e instanceof ParamFlowException){
result = result.error("104","热点参数限流了");
}
response.setStatus(500);
response.setCharacterEncoding("utf-8");
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getWriter(),result);
}
}
规则持久化
Sentinel规则的推送有三种模式
推送模式 | 说明 | 优点 | 缺点 |
---|---|---|---|
原始模式 | API将规则推送至客户端并直接更新到内存中,扩展写数据源 | 简单,无任何依赖 | 不保证一致性;规则保存在内存中,重启即消失。严重不建议用于生产环境。 |
pull模式 | 扩展写数据源,客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是RDBMS、文件等 | 简单,无任何依赖;规则持久化 | 不保证一致性;实时性不保证,拉取过于频繁也可能会有性能问题 |
push模式 | 扩展读数据源,规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用Nacos、Zookeeper等配置中心。这种方式有更好的实时性和一致性保证。生产环境下一般采用push模式的数据源。 | 规则持久化;一致性;快速 | 引入第三方依赖 |
push模式
生产环境下一般更常用的是push模式的数据源。对于push模式的数据源,如远程配置中心(Zookeeper、Nacos等),推送的操作不应由Sentinel客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是 配置中心控制台/Sentinel控制台 ------ 配置中心 ------- Sentinel数据源 ------ Sentinel,而不是经Sentinel数据源推送至配置中心,这样的流程就非常清晰了。
基于Nacos配置中心控制台实现推送
1.引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2.nacos配置中心配置流控规则
[
{
"resource": "/order/add",
"controlBehavior": 0,
"count": 10,
"grade": 1,
"limitApp": "default",
"strategy": 0
}
]
3.修改配置文件
#Sentinel相关配置
sentinel:
#持久化
datasource:
#可以自定义
flow-rule:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
dataId: order-service-flow-rule
rule-type: flow
Sentinel控制台规则同步到Nacos
规则同步到Nacos
会在后续文章中进行网关与Sentinel的整合。
最后
以上就是尊敬橘子为你收集整理的Sentinel服务雪崩 SentinelSentinel控制台 SpringCloudAlibaba整合Sentinel流控规则熔断降级规则Sentinel整合OpenFeign进行降级 热点参数流控系统保护规则 BlockException异常统一处理规则持久化Sentinel控制台规则同步到Nacos的全部内容,希望文章能够帮你解决Sentinel服务雪崩 SentinelSentinel控制台 SpringCloudAlibaba整合Sentinel流控规则熔断降级规则Sentinel整合OpenFeign进行降级 热点参数流控系统保护规则 BlockException异常统一处理规则持久化Sentinel控制台规则同步到Nacos所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复