一、添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
二、配置文件配置地址
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
三、流控模式介绍
直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式
关联:统计与当前资源相关的另一个资源触发阈值时,对当前资源限流
使用场景:比如用户支付时需要修改订单状态,同时用户要查询订单。查询和修改操作会争抢数据库锁,产生竞争。业务需求是有限支付和更新订单的业务,因此当修改订单业务触发阈值时,需要对查询订单业务限流。
链路:统计从指定链路访问到本资源的请求触发阈值时,对指定链路限流
例如有两条请求链路:
如果只希望统计从/test2进入到/common的请求,则可以这样配置:
注意:
1、Sentinel默认会将Controller方法做context整合,导致链路模式的流控失效,需要修改application.yml,添加配置:
spring:
cloud:
sentinel:
web-context-unify: false # 关闭context整合
2、Sentinel默认只标记Controller中的方法为资源,如果要标记其它方法(如service方法),需要利用@SentinelResource注解,示例:
@SentinelResource("goods")
public void queryGoods() {
System.err.println("查询商品");
}
四、流控效果
快速失败:QPS超过阈值时,拒绝新的请求。
warm up: QPS超过阈值时,拒绝新的请求;但QPS阈值是逐渐提升的,可以避免冷启动时高并发导致服务宕机。
排队等待:请求会进入队列,按照阈值允许的时间间隔依次执行请求;如果请求预期等待时长大于超时时间,直接拒绝。
五、热点参数限流
热点参数限流是分别统计参数值相同的请求,判断是否超过QPS阈值。并且可以对部分参数设置例外配置:
注意:热点参数限流对默认的SpringMVC资源无效,必须手动添加@SentinelResource注解
六、FeignClient整合Sentinel
Sentinel支持的雪崩解决方案:1、线程隔离(仓壁模式)2、降级熔断
(1)在application.yml中配置:feign.sentienl.enable=true
feign:
sentinel:
enabled: true # 开启Feign的Sentinel功能
(2)给FeignClient编写FallbackFactory并注册为Bean
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable throwable) {
// 创建UserClient接口实现类,实现其中的方法,编写失败降级的处理逻辑
return new UserClient() {
@Override
public User findById(Long id) {
// 记录异常信息
log.error("查询用户失败", throwable);
// 根据业务需求返回默认的数据,这里是空用户
return new User();
}
};
}
}
@Bean
public UserClientFallbackFactory userClientFallback(){
return new UserClientFallbackFactory();
}
(3)将FallbackFactory配置到FeignClient
@FeignClient(value = "userservice", fallbackFactory =UserClientFallbackFactory.class)
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
七、熔断降级策略
1、慢调用比例:超过指定时长的调用为慢调用,统计单位时长内慢调用的比例,超过阈值则熔断
2、异常比例:统计单位时长内异常调用的比例,超过阈值则熔断
3、异常数:统计单位时长内异常调用的次数,超过阈值则熔断
八、授权规则
授权规则可以对调用方的来源做控制,有白名单和黑名单两种方式。
Sentinel是通过RequestOriginParser这个接口的parseOrigin来获取请求的来源的。
public interface RequestOriginParser {
/**
* 从请求request对象中获取origin,获取方式自定义
*/
String parseOrigin(HttpServletRequest request);
}
所以在填写流控应用的时候,是根据自定义的RequestOriginParser来填写(比如在请求header上添加值来区分是网关过来的请求还是直接访问的服务的请求)
@Component
public class HeaderOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
String origin = request.getHeader("origin");
if(StringUtils.isEmpty(origin)){
return "blank";
}
return origin;
}
}
九、自定义返回方法
只需实现BlockExceptionHandler接口即可
@Component
public class SentinelBlockHandler implements BlockExceptionHandler {
@Override
public void handle(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, BlockException e) throws Exception {
String msg = "未知异常";
int status = 429;
if (e instanceof FlowException) {
msg = "请求被限流了!";
} else if (e instanceof DegradeException) {
msg = "请求被降级了!";
} else if (e instanceof ParamFlowException) {
msg = "热点参数限流!";
} else if (e instanceof AuthorityException) {
msg = "请求没有权限!";
status = 401;
}
httpServletResponse.setContentType("application/json;charset=utf-8");
httpServletResponse.setStatus(status);
httpServletResponse.getWriter().println("{\"message\": \"" + msg + "\", \"status\": " + status + "}");
}
}
十、配置规则持久化三种模式
1、原始模式:保存在内存
2、pull模式:保存在本地文件或数据库,定时去读取
3、push模式:保存在nacos,监听变更实时更新
通常生产环境采用push模式,需要修改Sentinel-dashboard的源码