sentinel
服务保护主要是限流和 熔断降级
sentinel客户端 会连接上 sentinel的控制台,获取到规则,,这些保护策略,,可以存放在nacos,或者zookeeper中,,,规则一旦发生了变更,,会将规则推送到各个服务中...
sentinel默认将流控规则写入到了内存里面,项目一重启,就会失效
sentinel定义的资源
- 所有的web接口均为资源
- 声明式:
SentinelResource去声明这个方法是个资源 - 编程式:
SphU直接用代码去限流,,捕获异常
sentinel中的规则
- 流量控制 FlowRule
- 熔断降级 DegradeRule
- 系统保护 SystemRule
- 来源访问控制 AuthorityRule
- 热点参数 ParamFlowRule
sentinel使用
sentinel服务台: https://sentinelguard.io/zh-cn/docs/dashboard.html
下载sentinel服务台:https://github.com/alibaba/Sentinel/releases
sentinel文档:https://github.com/alibaba/Sentinel/wiki/介绍
java导入sentinel:
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
sentinel自定义异常BlockException:
下面有很多实现类,,就是每一种规则违反之后会抛出不同的异常,,比如FlowException,
ParamFlowExcption,DegradeException,AuthorityException,SystemBlockException
这些异常会根据资源方式的不同,进行不同的处理,,,
资源方式:
- web接口
- @SentinelResource
- openfeign调用
- 编程式调用 SphU

- web接口
通过拦截器SentinelWebInterceptor处理,,这个拦截器如果捕获到了异常,,会去触发BlockExceptionHandler去执行相应的逻辑,,sentinel默认给了一个DefaultBlockExceptionHandler,如果需要自定义限流返回的json,,就需要自定义BlockExceptionHandler
java
package com.cj.order.exception;
import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.cj.common.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import java.io.PrintWriter;
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, String resourceName, BlockException e) throws Exception {
// 设置响应码
response.setStatus(429); // too many request
// 这个必须在getWriter前面
response.setContentType("application/json;charset=utf-8");
// 返回自定义错误json
PrintWriter writer = response.getWriter();
System.out.println("e.getClass() = " + e.getClass());
R error = R.error(500, resourceName + "被sentinel限制了,原因:" + e.getMessage());
String json = objectMapper.writeValueAsString(error);
writer.write(json);
writer.flush();
writer.close();
}
}
- @SentinelResource : 标注指定的方法
这个注解的拦截逻辑是写在SentinelResourceAspect切面中,,先获取上面有没有blockHandler属性标记的函数,,如果有就执行,,如果没有,继续找fallback属性标记的函数,,如果也没有,就去找defaultFallback属性对应的函数,,,如果这三个属性都没有设置函数,,直接抛出错误,,
所以使用@SentinelResource需要给他配置一个兜底函数
java
@SentinelResource(value = "createOrder",blockHandler ="createOrderFallback" )
@Override
public Order createOrder(Long productId, Long userId) {
System.out.println("doing....");
// Product product = getProductFromRemoteWithLoadBalance(productId);
// Product product = getProductFromRemoteWithLoadBalancerAndAnnotation(productId);
// feign完成远程调用
Product product = productFeignClient.getProductById(productId);
Order order = new Order();
order.setId(1L);
BigDecimal totalAmount= product.getPrice().multiply(new BigDecimal(product.getNum()));
order.setTotalAmount(totalAmount);
order.setUserId(userId);
order.setNickName("zhangsan");
order.setAddress("chengdu");
List<Product> productList = Arrays.asList(product);
// 远程查询商品列表
order.setProductList(productList);
return order;
}
// 兜底回调,,跟这个方法的签名一样 ===> 可以多加一个exception参数
public Order createOrderFallback(Long productId, Long userId, BlockException e) {
Order order = new Order();
order.setId(0L);
order.setNickName("无效订单");
order.setAddress(e.getMessage());
return order;
}
blockHandler和fallback区别:
- blockHandler : 被sentinel熔断,限流触发的异常
- fallback : 除了sentinel的错误,,业务出错,,也会执行fallback
- OpenFeign远程调用兜底
openfeign使用的时候,有fallback,,需要配置sentinel的包,才能自动使用降级的逻辑,,
是因为SentinelFeignAutoConfiguration: 配置了 sentinel和openfeign的整合,,@FeignClient中的fallback,,sentinel会去调这个fallback
4.SphU : 底层代码,,直接编程式的写代码,,如果违背了规则,就会抛出BlockException
流控模式
链路策略
不同的链路对应不同的限流策略,尽管调用的是同一个方法,,在设置限流的时候也能够分链路设置,比如说,一个是普通的创建订单,,不遵循规则,,一个是秒杀的创建订单,需要被限流
需要开启不是同一个上下文: spring.sentinel.web-context-unify=false

关联
一开始限流规则不会生效,,只有当关联的资源被大量访问之后,,对应的限流规则才会生效,,,
比如说: 读和写都是操作数据库,,,当订单量的写比较大的时候,,对读进行限流,,就是优先写,,这就是关联策略,读写是相关的,,仅仅在写的请求比较多的时候,读的限流才会触发。。。
当系统里面出现资源竞争的时候,,一般使用关联策略进行限制

流控效果
快速失败
如果超出了阈值,,直接抛出一个BlockException
Warm up : 预热,冷启动
他一开始不会放你指定的qps那么多请求,,会先放1/3 ,慢慢增加,直到增加到高水位线,,会让系统慢慢适应,不至于,系统还没反应过来,就挂掉了
匀速排队
多余的请求会排队,有一个timeout最大排队时间,,超时的请求会被丢掉,,
漏桶算法
熔断降级 DegradeRule
断路器有三个状态:
- 关闭
- 打开
- half open 半开: 放一个请求过去进行探测,如果放行的这个请求能调用,断路器就关掉

- 慢调用比例
- 异常比例
- 异常数

这个图的意思就是5s之内,请求数大于5,,response time超过1s算慢调用,如果达到了慢调用的阈值,,就熔断x秒,,若干秒之后,发送一个试探请求,如果恢复了,就关闭熔断器,否则,继续熔断
热点规则
本质上还是限流,只是这个限流可以针对具体的参数,,也就是精确到参数级别的限流
比如说:
- 秒杀下单,每个用户单独限制qps
- 6号是用户vvip,不限制qps,,也能排除指定用户的限流
- 不允许访问某个id的商品,,就把这个商品id的规则设置为qps为0
授权规则
只有这些个服务才能调用这个资源,,这个规则没什么用,因为有网关

系统规则
全系统触发,一般不用