Sentinel
资源
通过@SentinelResource
来标识需要由sentinel管理,保护的资源。对于主流框架sentinel进行了适配,所有的Web接口均为资源
规则
通过Sentinel控制台我们可以定义流量控制,熔断降级,系统保护,来访控制,热点参数等的规则,可以将其作用于资源上。
整合sentinel
官网:https://sentinelguard.io
sentinel面板下载地址:https://github.com/alibaba/Sentinel/releases
- 下载好sentinel面板
- 引入sentinel依赖
spring-cloud-starter-alibaba-sentinel
- 由于所有微服务都可能会用到sentinel,那么在管理微服务的模块(services模块)中添加该依赖
- 编写yml配置文件
- 要用到sentinel的微服务都有在yml文件中添加该段
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
eager: true #让项目一启动就让该项目连上dashboard
异常处理
当请求违背规则时会抛出一个BlockException异常,而具体来分又会抛出FlowException(流量控制异常);;ParamFlowException(热点参数异常);DegradeException(熔断降级异常);AuthorityException(权限控制异常);SystemBlockException(系统保护异常)。由于资源的不同,又会又不同的异常处理机制。
web接口异常
当对web接口的访问被sentinel规则限制会抛出该异常(可以理解为作用于controller)
自定义web请求异常访问
默认情况下会使用springmvc的SentinelWebInterceptor(web拦截器),它只会使用默认的BlockExceptionHandler进行处理(返回一个页面),而实际开发中,我们需要的是返回一个json对象。
要实现该功能我们需要使用@SentinelResource
注解来标注作用的资源,然后去实现BlockExceptionHandler,并将其放入到ioc容器中即可
下面这个例子会对创建订单请求进行流量控制,并且自定义返回的错误信息为json串
1.添加流控规则
我们可以在sentinel控制台中看到名为/create
的资源,该资源是一个远程调用接口,用以获取商品数据
然后点击流控,对其添加流控规则为QPS,单机阈值为1.
此时如果多次发送请求则会返回一个默认的错误页面
2.自定义异常返回结果
// model模块 com.atli.common.R
// 用于定义所有响应
@Data
public class R{
private Integer code;
private String msg;
private Object data;
public static R ok(){
R r = new R();
r.setCode(200);
return r;
}
public static R ok(String msg,Object data){
R r = new R();
r.setCode(200);
r.setMsg(msg);
r.setData(data);
return r;
}
p public static R error(){
R r = new R();
r.setCode(500);
return r;
}
public static R error(Integer code,String msg){
R r = new R();
r.setCode(code);
r.setMsg(msg);
return r;
}
}
// com.atli.order.exception.MyBlockExceptionHandler
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler{
// 这是springMVC整合了jackson的json工具
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public void handle(HttpServletRequest request,HttpServletResponse response,String resourceName,BlockException e) throws Exception{
PrintWriter writer = response.getWriter();
response.setContentType("application/json;charset=utf-8");
R.error(500,resourceName+"bei1Sentinel限制:"+e.getMessage())
writer.write(objectMapper.writeValueAsString(error));
}
}
SentinelResource资源
@SentinelResource
注解可以用来声明资源,一般用在非controller层(controller层是接口本身默认就是资源),在SentinelResourceAspect切面中,切点表达式定义了使用该注解注解的方法都会被sentinel切入
// com.atli.order.service.impl.OrderServiceImpl
// 这里将一个远程调用方法声明为资源,用以管控
// 资源会展示在sentinel控制台中,可以对其进行流控/熔断/热点/授权等设置
// blokHandle用于指定兜底回调,若没有指定则会交给SpringBoot全局异常处理器进行处理
@SentinelResource(value="createOrder",blockHandle = "createOrderFallback")
@Override
public Order createOrder(Long productId , Long userId){
//之前写的远程调用商品服务的代码
}
// 定义兜底回调,该回调会在createOrder方法调用失败后执行(被sentinel限制)
// 要注意,该回调除开方法名外要与原方法一致,并且可以在参数列表中添加一个异常
public Order createOrderFallback(Long productId , Long userId , BlockException e){
//兜底回调的逻辑,比如返回一个全为特殊值(0,默认等)的Order对象进行返回
}
OpenFeign调用
可以去看OpenFeign的默认返回章节
流控规则
总的来说,流控的主要目的是限制多余请求,以保护系统资源不被耗尽,保护系统的稳定性
在sentinel控制台我们可以新增流控规则,可以对来源,阈值类型,单机阈值,集群,流控模式,流控效果等进行设置
- 资源名
- 用以表示要进行限制的资源名称
- 针对来源
- 表示对资源访问的来源,默认为default,表示所有来源
- 可以类比为http请求的发起方
- 阈值类型
- QPS
- 表示在1s内最多的请求个数
- 并发线程数
- 效果同QPS,但由于要统计线程数,会影响性能
- QPS
- 单机阈值
- 表示一个服务器最多能接收的请求个数
- 是否集群
- 若勾选,会由集群阈值模式选项,分为单机均摊和总体阈值
- 此时单机阈值选项会变为均摊阈值
- 单机均摊则每台阈值为设定值。总体阈值则整个集群的最大请求数
- 流控模式
- 直接策略
- 直接对该资源进行限制
- 关联策略
- 关联资源
- 与自身资源需要进行关联的资源
- 当资源A和B都访问同一资源C时,若对资源A设置了关联策略,并将关联资源设置为了B,那么当访问量过大时会优先满足资源B的需求,对资源A进行限制
- 关联资源
- 链路策略
- 要使用链路策略我们还需要在配置文件中对sentinel的web-context-unify设置为false,该配置项表示是否要统一web的上下文
- 入口资源
- 调用链路的入口
- 在调用链路中,可能会有多条从入口到目标资源的资源路径,通过链路策略,我们可以管控从入口到目标资源路径上的资源(例如有2个并联资源,若对A不限制,那么对目标资源的限制其实作用在B上)
- 直接策略
- 流控效果
- 快速失败
- 超出阈值的请求直接抛出异常
- Warm Up(冷启动)
- QPS,最大请求数
- Period 冷启动周期
- 例:假设QPS=3,Period=3,那么当大量请求到达后QPS会从0开始,递增Period次,到达设置的QPS值,之后一直按照QPS的值进行限流
- 排队等待
- timeout
- 排队超时事件
- 当大量请求到达后,该资源会将所有请求进行排队,超过了timeout时间的请求会被丢弃
- 例:QPS=2,timeout=3,那么每次都会将6个请求放入到队列,其余请求都会被抛弃
- timeout
- 只有快速失败支持链路和关联策略
- 快速失败
熔断规则
雪崩效应:
当微服务集群中某个服务存在问题无法及时响应时,调用它的其他微服务就会积压请求,使得自身资源被快速消耗,无法及时响应数据。由于一个服务异常而导致一堆服务异常的这种现象被称为雪崩
熔断降级:
为了避免雪崩效应,让失败的请求快速返回不积压,切断不稳定调用的机制就称为熔断降级。
熔断降级作为保护自身的手段,通常在调用端进行配置
-
断路器:
- 闭合
- 正常访问
- 打开
- 发生熔断,在熔断时长到达之前都拒绝访问
- 熔断时长结束后进入半开状态
- 半开
- 先放行一个请求作为探测
- 若成功则断路器闭合
- 若失败则断路器重新打开
- 闭合
-
熔断策略
- 慢调用比例
- 最大RT:设置统计的最大响应时长
- 比例阈值:在统计时长内超过最大RT的请求数的比例大于比例阈值则熔断
- 异常比例
- 在统计时长内有超过比例阈值的异常调用(执行了兜底回调)会发生熔断
- 异常数
- 在统计时长内超过了设置异常数的异常请求则发生熔断
- 慢调用比例
热点规则
热点是经常访问的数据。热点参数限流可以看作是一种特殊的流量控制,仅对包含热点参数的资源调用生效
要使用热点规则,需要对接受请求的api接口添加@SentinelResource
注解,并指定兜底回调,之后再在sentinel控制台对其请求的参数进行限制
例如,我需要同一个用户不能重复发起请求
@GetMapping("/seckill")
@SentinelResource(value = "seckill-order",fallback = "seckillFallback")
public Order seckill(@RequestParam("userId") Long userId,@RequestParam("productId") Long productId){
Order order = orderService.createOrder(productId,userId);
order.setId(Long.MAX_VALUE);
return order;
}
// sentinel异常机制中先走blockHandle异常,若无才走fallback异常
// 这里是fallback回调,使用该回调可以处理所有异常,blockHandle只能处理流控异常
public Order seckillFallback(Long userId,Long productId,Throwable exception){
//需要兜底返回的内容
}
此时我们只需要在控制台中找到该资源,然后点击添加熔断,将参数索引设置为0,单机阈值设置为1,统计窗口时长也设置为1,那么在1s内每个用户就都只能发送一个请求