SpringCloudAlibaba--09——sentinel
参考地址:蚂蚁课堂
* 持久化的四种方案
默认的情况下Sentinel的规则是存放在内存中,如果Sentinel客户端重启后,Sentinel数据规则可能会丢失。
解决方案:
Sentinel持久化机制支持四种持久化的机制。
- 本地文件
- 携程阿波罗
- Nacos
- Zookeeper
基于Nacos持久化我们的数据规则
Nacos平台中创建我们的流控规则
meitemayikt-order-sentinel
[ { "resource": "/ getOrderSentinel", "limitApp": "default", "grade": 1, "count": 5, "strategy": 0, "controlBehavior": 0, "clusterMode": false } ]
|
如图:
resource:资源名,即限流规则的作用对象
limitApp:流控针对的调用来源,若为 default 则不区分调用来源
grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
count:限流阈值
strategy:调用关系限流策略
controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
clusterMode:是否为集群模式
@SentinelResource(value = "getOrderSentinel", blockHandler = "getOrderQpsException") @RequestMapping("/getOrderSentinel") public String getOrderSentinel() { return "getOrderSentinel"; }
别忘记依赖:
<!--sentinel 整合nacos --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <version>1.5.2</version> </dependency>
相关配置:
sentinel:
transport:
dashboard: 127.0.0.1:8718
eager: true
datasource:
ds:
nacos:
### nacos连接地址
server-addr: localhost:8848
## nacos连接的分组
group-id: DEFAULT_GROUP
###路由存储规则
rule-type: flow
### 读取配置文件的 data-id
data-id: meitemayikt-order-sentinel
### 读取培训文件类型为json
data-type: json
SpringCloud网关如何整合sentinel实现限流
查看到sentinel中文社区文档 https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81
相关核心配置
Maven依赖配置
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> <version>2.0.0.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId> <version>1.6.0</version> </dependency>
配置:
gateway:
routes:
- id: my-member
uri: lb://meitemayikt-member
predicates:
- Path=/meitemayikt-member/**
- id: mayikt
uri: http://www.mayikt.com
predicates:
- Path=/mayikt/**
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter; import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler; import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.web.reactive.result.view.ViewResolver; import java.util.Collections; import java.util.List; @Configuration public class GatewayConfiguration { private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { // Register the block exception handler for Spring Cloud Gateway. return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public GlobalFilter sentinelGatewayFilter() { return new SentinelGatewayFilter(); } }
加载网关流控规则:
@Slf4j @Component public class SentinelApplicationRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { initGatewayRules(); } /** * 配置限流规则 */ private void initGatewayRules() { Set<GatewayFlowRule> rules = new HashSet<>(); rules.add(new GatewayFlowRule("mayikt") // 限流阈值 .setCount(1) // 统计时间窗口,单位是秒,默认是 1 秒 .setIntervalSec(1) ); GatewayRuleManager.loadRules(rules); } }
如何修改限流错误提示
public class JsonSentinelGatewayBlockExceptionHandler implements WebExceptionHandler { public JsonSentinelGatewayBlockExceptionHandler(List<ViewResolver> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) { } @Override public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) { ServerHttpResponse serverHttpResponse = exchange.getResponse(); serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); byte[] datas = "{\"code\":403,\"msg\":\"API接口被限流\"}".getBytes(StandardCharsets.UTF_8); DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(datas); return serverHttpResponse.writeWith(Mono.just(buffer)); } }
然后去替换掉配置类里的halder
@Bean @Order(Ordered.HIGHEST_PRECEDENCE) public JsonSentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { // Register the block exception handler for Spring Cloud Gateway. return new JsonSentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); }
sentinel实现熔断降级
https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求发生堆积。Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。
降级的策略:分3种
1.平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
2.异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
3.异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
平均的响应时间
如果在1s秒,平均有5个请求的响应时间大于配置的10rt毫秒时间 阈值,则会执行一定时间窗口的熔断和降级。
@SentinelResource(value = "getOrderDowngradeRtType", fallback = "getOrderDowngradeRtTypeFallback") @RequestMapping("/getOrderDowngradeRtType") public String getOrderDowngradeRtType() { try { Thread.sleep(300); } catch (Exception e) { } return "getOrderDowngradeRtType"; } public String getOrderDowngradeRtTypeFallback() { return "服务降级啦,当前服务器请求次数过多,请稍后重试!"; }
异常的比例
当我们每秒的请求大于5的时候,会根据一定比例执行我们的熔断降级的策略。
@SentinelResource(value = "getOrderDowngradeErrorType", fallback = "getOrderDowngradeErrorTypeFallback") @RequestMapping("/getOrderDowngradeErrorType") public String getOrderDowngradeErrorType(int age) { int j = 1 / age; return "正常执行我们的业务逻辑"; } public String getOrderDowngradeErrorTypeFallback(int age) { return "服务降级啦,当前服务器请求次数过多,请稍后重试!"; }
异常的次数
当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。