一、降级规则

1、官网 熔断降级 · alibaba/Sentinel Wiki (github.com)

2、说明

Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,
让请求快速失败,避免影响到其它的资源而导致级联错误。
当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。

 

Sentinel的断路器是没有半开状态的

半开的状态系统自动去检测是否请求有异常,
没有异常就关闭断路器恢复使用,
有异常则继续打开断路器不可用。具体可以参考Hystrix

降级策略实战

1)、RT  平均响应时间 (DEGRADE_GRADE_RT)

java 熔断限流框架 spring 限流 熔断 降级_断路器

2)、异常比例

java 熔断限流框架 spring 限流 熔断 降级_限流_02

3)、异常数

java 熔断限流框架 spring 限流 熔断 降级_java 熔断限流框架_03

二、热点key限流

1、何为热点

热点即经常访问的数据,很多时候我们希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其它操作

比如  商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制,用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

 

兜底方法  分为系统默认和客户自定义,两种

之前的case,限流出问题后,都是用sentinel系统默认的提示:Blocked by Sentinel (flow limiting)

我们能不能自定?类似hystrix,某个方法出问题了,就找对应的兜底降级方法?

结论 : 从HystrixCommand 到@SentinelResource

代码

@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1, 
                         @RequestParam(value = "p2",required = false) String p2){
    return "------testHotKey";
}
public String dealHandler_testHotKey(String p1,String p2,BlockException exception)
{
    return "-----dealHandler_testHotKey";
}

sentinel系统默认的提示:Blocked by Sentinel (flow limiting)

java 熔断限流框架 spring 限流 熔断 降级_断路器_04

限流模式只支持QPS模式,固定写死了。(这才叫热点)
@SentinelResource注解的方法参数索引,0代表第一个参数,1代表第二个参数,以此类推
单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。
上面的抓图就是第一个参数有值的话,1秒的QPS为1,超过就限流,限流后调用dealHandler_testHotKey支持方法。

 @SentinelResource(value = "testHotKey") 异常打到了前台用户界面看到,不友好

@SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey")

用了我们自己定义的,方法testHotKey里面第一个参数只要QPS超过每秒1次,马上降级处理

 

上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流

特例 假如当p1的值等于5时,它的阈值可以达到200

java 熔断限流框架 spring 限流 熔断 降级_限流_05

 

 热点参数的注意点,参数必须是基本类型或者String

 

@SentinelResource
处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理;

RuntimeException
int age = 10/0,这个是java运行时报出的运行时异常RunTimeException,@SentinelResource不管

总结
@SentinelResource主管配置出错,运行出错该走异常走异常

 

 

三、系统规则

是什么 :系统自适应限流 · alibaba/Sentinel Wiki (github.com)

java 熔断限流框架 spring 限流 熔断 降级_自定义_06

 配置全局QPS

 

java 熔断限流框架 spring 限流 熔断 降级_java 熔断限流框架_07

四、@SentinelResource

1、按资源名称限流+后续处理

配置表示1秒钟内查询次数大于1,就跑到我们自定义的处流,限流

java 熔断限流框架 spring 限流 熔断 降级_自定义_08

 代码

@GetMapping("/byResource")
    @SentinelResource(value = "byResource",blockHandler = "handleException")
    public CommonResult byResource()
    {
        return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
    }
    public CommonResult handleException(BlockException exception)
    {
        return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
    }

测试 超过上述,疯狂点击,返回了自己定义的限流处理信息,限流发生

java 熔断限流框架 spring 限流 熔断 降级_自定义_09

额外问题  此时关闭问服务8401, Sentinel控制台,流控规则消失了 

2、按照Url地址限流+后续处理

@GetMapping("/rateLimit/byUrl")
    @SentinelResource(value = "byUrl")
    public CommonResult byUrl()
    {
        return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));
    }

java 熔断限流框架 spring 限流 熔断 降级_断路器_10

 点击次数超过一秒钟一次 提示错误

 

java 熔断限流框架 spring 限流 熔断 降级_断路器_11

上面兜底方案面临的问题

1    系统默认的,没有体现我们自己的业务要求。
 
2  依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观。
 
3  每个业务方法都添加一个兜底的,那代码膨胀加剧。
 
4  全局统一的处理方法没有体现。

3、客户自定义限流处理逻辑

创建CustomerBlockHandler类用于自定义限流处理逻辑

public class CustomerBlockHandler {
    public static CommonResult handlerException(BlockException exception)
    {
        return new CommonResult(4444,"按客戶自定义,global handlerException----1");
    }
    public static CommonResult handlerException2(BlockException exception)
    {
        return new CommonResult(4444,"按客戶自定义,global handlerException----2");
    }
}

java 熔断限流框架 spring 限流 熔断 降级_java 熔断限流框架_12

 

java 熔断限流框架 spring 限流 熔断 降级_断路器_13

 

 

java 熔断限流框架 spring 限流 熔断 降级_java 熔断限流框架_14

点击次数超过一秒钟一次提示自定义异常

java 熔断限流框架 spring 限流 熔断 降级_java 熔断限流框架_14