Spring Cloud Alibaba快速入门-Sentinel热点参数限流
文章目录
- 前言
- 需求1:每个用户秒杀 QPS 不得超过 1(秒杀下单 userld 级别)
- 需求2:userId为8的用户是vip,不限制QPS(例外情况)
- 需求3:productId为666是下架商品,不允许访问
- 兜底回调的两种写法:fallback和blockHandler
- fallback+BlockException
- seckillFallback+BlockException
- fallback+Throwable
- 授权规则与系统规则
前言
文档:https://sentinelguard.io/zh-cn/docs/parameter-flow-control.html
何为热点?热点即经常访问的数据。
很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
总结:热点参数限流其实就是控制到接口参数的限流。
需求1:每个用户秒杀 QPS 不得超过 1(秒杀下单 userld 级别)
效果:携带此参数的参与流控,不携带不流控
//热点参数限流
@GetMapping("/seckill")
//先为这个接口创建一个资源
@SentinelResource(value = "my-seckill-order",fallback = "seckillFallback")
public Order seckill(@RequestParam(value = "userId",required = false) Long userId,@RequestParam(value = "productId",defaultValue = "1000") Long productId){Order order = orderService.createOrder(productId, userId);order.setId(Long.MAX_VALUE);return order;
}public Order seckillFallback(Long userId,Long productId, Throwable exception){System.out.println("seckillFallback....");Order order = new Order();order.setId(productId);order.setUserId(userId);order.setAddress("异常信息:"+exception.getClass());return order;
}
配置热点规则
可以看到新添加的资源名称,给接口新添加的资源设置热点
给接口中第一个参数(userId)设置每秒限制访问一个请求的阈值
访问接口
当不传递userId时,则不会限制接口
需求2:userId为8的用户是vip,不限制QPS(例外情况)
点击
点击高级选项
点击保存
调用接口时可以发现,当userId=8时不受到userId参数设置的每秒访问一次的限制。
需求3:productId为666是下架商品,不允许访问
新增一个热点规则
调用接口时可以发现,当productId=666时每秒访问成功一次。
兜底回调的两种写法:fallback和blockHandler
在@SentinelResource的属性中,fallback和blockHandler属性通常用于定义服务降级逻辑。下面是它们的区别:
fallback方法:
- 只针对当前方法的异常进行处理,处理所有类型的异常,包括业务异常
- 当被注解的方法执行失败(例如抛出异常)时调用。
- 主要用于处理业务逻辑异常,提供一种默认的返回值或者备用逻辑。
blockHandler方法:
- 方法参数必须以BlockException结尾
- 仅在资源被流量控制规则(限流、熔断)阻止时触发
- 专门处理BlockException及其子类异常
总结来说,fallback主要用于业务异常的优雅降级,而blockHandler则更多地与系统的流量防护机制相关联。
@SentinelResource注解会优先处理blockHandler,没有blockHandler才走fallback。
blockHandler只能处理BlockException异常,而fallback可以处理所有的异常。
fallback+BlockException
@GetMapping("/seckill")//先为这个接口创建一个资源@SentinelResource(value = "my-seckill-order",fallback = "seckillFallback")public Order seckill(@RequestParam(value = "userId",required = false) Long userId,@RequestParam(value = "productId",defaultValue = "1000") Long productId){Order order = orderService.createOrder(userId,productId);order.setId(Long.MAX_VALUE);return order;}public Order seckillFallback(Long userId,Long productId, BlockException exception){
// public Order seckillFallback(Long userId,Long productId, Throwable exception){System.out.println("seckillFallback....");Order order = new Order();order.setId(productId);order.setUserId(userId);order.setAddress("异常信息:"+exception.getClass());return order;}
sentinel设置热点参数限流规则
后台日志
2025-03-05T07:18:38.297+08:00 ERROR 31968 --- [qf-service-order] [nio-8081-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.reflect.UndeclaredThrowableException] with root causecom.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException: 8
seckillFallback+BlockException
@GetMapping("/seckill")//先为这个接口创建一个资源@SentinelResource(value = "my-seckill-order",blockHandler = "seckillFallback")public Order seckill(@RequestParam(value = "userId",required = false) Long userId,@RequestParam(value = "productId",defaultValue = "1000") Long productId){Order order = orderService.createOrder(userId,productId);order.setId(Long.MAX_VALUE);return order;}public Order seckillFallback(Long userId,Long productId, BlockException exception){
// public Order seckillFallback(Long userId,Long productId, Throwable exception){System.out.println("seckillFallback....");Order order = new Order();order.setId(productId);order.setUserId(userId);order.setAddress("异常信息:"+exception.getClass());return order;}
fallback+Throwable
@GetMapping("/seckill")//先为这个接口创建一个资源@SentinelResource(value = "my-seckill-order",fallback = "seckillFallback")public Order seckill(@RequestParam(value = "userId",required = false) Long userId,@RequestParam(value = "productId",defaultValue = "1000") Long productId){Order order = orderService.createOrder(userId,productId);order.setId(Long.MAX_VALUE);return order;}// public Order seckillFallback(Long userId,Long productId, BlockException exception){public Order seckillFallback(Long userId,Long productId, Throwable exception){System.out.println("seckillFallback....");Order order = new Order();order.setId(productId);order.setUserId(userId);order.setAddress("异常信息:"+exception.getClass());return order;}
业务中有异常可以使用fallback进行处理。
授权规则与系统规则
授权规则和系统规则很少使用,流控应用中填写限制哪些应用的应用名,通常会使用网关、权限框架等限制。
而系统资源一般由k8s控制。