SpringCloudAlibaba→Sentinel:熔断、限流、降级 |
您所在的位置:网站首页 › sentinel限流springboot › SpringCloudAlibaba→Sentinel:熔断、限流、降级 |
Sentinel熔断、限流、降级
1 SpringBoot集成1.1 @SentinelResource注解1.2 blockHandler1.3 fallback1.4 defaultFallback
2 限流、熔断规则2.1 流量控制2.2 熔断2.3 系统自我保护2.4 热点数据
3 OpenFeign支持3.1 fallback3.2 fallbackFactory
工程简介: 在我们项目中,用户请求通过 hailtaxi-gateway路由到 hailtaxi-driver 或者 hailtaxi-order,还有可能在 hailtaxi-order 中使用feign调用 hailtaxi-driver ,所以我们有可能在单个服务中实现熔断限流,也有可能要集成feign调用实现熔断限流,还有可能在微服务网关中实现熔断限流。我们接下来一步一步实现每一种熔断限流操作。 1 SpringBoot集成如果在SpringBoot项目中使用Sentinel,首先需要引入 spring-cloud-starter-alibaba-sentinel 依赖,并使用 @SentinelResource标识资源。 com.alibaba.cloud spring-cloud-starter-alibaba-sentinel 2.2.5.RELEASE 1.1 @SentinelResource注解@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性: 用户在打车的时候,会查询司机信息,如果司机不存在,此时会报错,代码如下: ①在 hailtaxi-driver工程中引入 spring-cloud-starter-alibaba-sentinel 依赖,依赖如下: com.alibaba.cloud spring-cloud-starter-alibaba-sentinel 2.2.5.RELEASE我们先添加一个方法 blockExHandler ()用来处理程序发生 BlockException 异常的时候(该方法和需要降级的方法在一个类),执行默认操作,代码如下: /*** * BlockException异常处理 */ public Driver blockExHandler(String id, BlockException ex) { Driver driver = new Driver(); driver.setId(id); driver.setName("系统繁忙,请稍后再试!"); return driver; }②我们为 info()方法添加一个 @SentinelResource注解,用来标注资源,表示当前方法需要执行限流、降级。在注解中添加value属性,用来标注资源,说白了就是给当前资源起个名字。 blockHandler用来表示当前方法发生 BlockException 异常的时候,将处理流程交给指定的方法 blockExHandler()处理,此时 blockExHandler() 方法必须和抛出异常的方法在同一个类中,这是一种降级操作,代码如下:
此时再访问访问http://localhost:18081/driver/info/3测试出错效果如下: 如果我们希望抛出任何异常都能处理,都能调用默认处理方法,而并非只是 BlockException 异常才调用,此时可以使用 @SentinelResource 的 fallback属性,代码如下: 上面无论是 blockHandler 还是 fallback ,每个方法发生异常,都要为方法独立创建一个处理异常的方法,效率非常低,我们可以使用@SentinelResource 注解的 defaultFallback 属性,为一个类指定一个全局的处理错误的方法,代码如下: 我们访问 http://localhost:18081/driver/info/3效果如下: 上面的@SentinelResource里的一些属性指定了发生了异常的时候的兜底方法,也就是降级。下面的限流、熔断同样可以降级。 简单理解:@SentinelResource指定属性是 发生异常后降级。 限流是达到设置的限流阈值后进行降级走兜底方法处理。 熔断是达到熔断阈值后进行降级处理。 Sentinel支持多种限流规则,规则我们可以在代码中直接定义,规则属性如下: 理解上面规则的定义之后,我们可以通过调用FlowRuleManager.loadRules()方法来用硬编码的方式定义流量控制规则。 1)QPS流量控制 我们先实现流量基于QPS控制,在hailtaxi-driver 的 DriverApplication 启动类上添加如下方法加载限流规则,当 DriverApplication 初始化完成之后加载规则,代码如下: /*** * 初始化规则 */ @PostConstruct private void initFlowQpsRule() { //规则集合 List rules = new ArrayList(); //定义一个规则 FlowRule rule = new FlowRule("info"); // 设置阈值 rule.setCount(2); //设置限流阈值类型 rule.setGrade(RuleConstant.FLOW_GRADE_QPS); //default,代表不区分调用来源 rule.setLimitApp("default"); //将定义的规则添加到集合中 rules.add(rule); //加载规则 FlowRuleManager.loadRules(rules); }我们访问 http://localhost:18081/driver/info/1此时不会抛出异常,但是频繁刷新,则会调用降级方法,效果如下: 2)线程数流量控制 我们修改限流阈值类型,代码如下: 熔断规则包含下面几个重要的属性: 我们来测试一下平均响应时间,在程序中休眠10秒中,再执行访问,代码如下: Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。 系统规则包含下面几个重要的属性: 在hailtaxi-driver的 主启动类中创建如下方法,代码如下: /*** * 系统自我保护 */ @PostConstruct private void initSystemRule() { //系统自我保护集合 List rules = new ArrayList(); //创建系统自我保护规则 SystemRule rule = new SystemRule(); //CPU使用率 值为0-1,-1 (不生效) rule.setHighestCpuUsage(0.2); //所有入口资源的 QPS,-1 (不生效) rule.setQps(10); //入口流量的最大并发数,-1 (不生效) rule.setMaxThread(5); //所有入口流量的平均响应时间,单位:秒,-1 (不生效) rule.setAvgRt(5); //load1 触发值,用于触发自适应控制阶段,系统最高负载,建议取值 CPU cores * 2.5 rule.setHighestSystemLoad(20); //将规则加入到集合 rules.add(rule); SystemRuleManager.loadRules(rules); }我们可以测试CPU使用率自我保护,如下效果: 何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如: 1:商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制 2:用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制 热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。 Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式。 要使用热点参数限流功能,需要引入以下依赖: com.alibaba.csp sentinel-parameter-flow-control 1.8.1然后为对应的资源配置热点参数限流规则,并在 entry 的时候传入相应的参数,即可使热点参数限流生效。 热点参数规则( ParamFlowRule )类似于流量控制规则( FlowRule ): 我们可以对热门参数比如下标为0的参数流量进行控制,对热点数据执行特殊限流,比如参数值为tj的时候执行限流,在 Driver的主启动类中创建限流配置,代码如下: /*** * 热点参数初始化 */ @PostConstruct private static void initParamFlowRules() { ParamFlowRule rule = new ParamFlowRule("search") //参数下标为0 .setParamIdx(0) //限流模式为QPS .setGrade(RuleConstant.FLOW_GRADE_QPS) //统计窗口时间长度(单位为秒) .setDurationInSec(10) //流控效果(支持快速失败和匀速排队模式) //CONTROL_BEHAVIOR_DEFAULT:限流行为,直接拒绝 //CONTROL_BEHAVIOR_WARM_UP:限流行为,匀速排队 //CONTROL_BEHAVIOR_RATE_LIMITER:限流行为,匀速排队 .setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT) //最大排队等待时长(仅在匀速排队模式生效 CONTROL_BEHAVIOR_RATE_LIMITER) //.setMaxQueueingTimeMs(600) //最大阈值为5 .setCount(5); // 为特定参数单独设置阈值. //如下配置:当下标为0的参数值为tj的时候,阈值到达2的时候则执行限流 ParamFlowItem item = new ParamFlowItem() //参数类型为int类型 .setClassType(String.class.getName()) //设置阈值为2 .setCount(2) //需要统计的值 .setObject(String.valueOf("tj")); rule.setParamFlowItemList(Collections.singletonList(item)); //加载热点数据 ParamFlowRuleManager.loadRules(Collections.singletonList(rule)); }我们访问 http://localhost:18081/driver/search/shenzhen 的时候,连续执行5次,才会限流,效果如下: Sentinel 适配了 Feign 组件。如果想使用,除了引入 spring-cloud-starter-alibaba-sentinel的依赖外还需要 2 个步骤: 配置文件打开 Sentinel 对 Feign 的支持:feign.sentinel.enabled=true加入 spring-cloud-starter-openfeign依赖使 Sentinel starter 中的自动化配置类生效
我们把之前的案例中 @SentinelResource相关注解全部注释掉,再实现Feign集成。 ①在 hailtaxi-driver、hailtaxi-order中引入 OpenFeign 依赖,配置如下: com.alibaba.cloud spring-cloud-starter-alibaba-sentinel 2.2.5.RELEASE org.springframework.cloud spring-cloud-starter-openfeign②还需要在Feign调用客户端(也就是 hailtaxi-order )中开启Feign的支持,配置如下: ①我们可以为Feign接口创建一个实现类,在实现类中处理程序异常降级处理方法,代码如下: @Component public class DriverFeignFallback implements DriverFeign { /** * status()降级处理方法 */ @Override public Driver status(String id, Integer status) { Driver driver = new Driver(); driver.setId(id); driver.setStatus(status); driver.setName("系统比较繁忙,请您稍后再试!"); return driver; } }②我们还需要在Feign接口上添加 fallback 属性指定讲解处理的类,代码如下: 注意: 此时运行,会发生如下问题:parseAndValidatateMetadata(Ljava/lang/Class;)Ljava/util/List; 出现上面问题的主要原因是当前SpringCloud版本存在问题。 Hoxton.SR1中, fegin.context 接口方法的定义为parseAndValidatateMetadata Hoxton.SR3中, fegin.context 接口方法的定义为parseAndValidateMetadata 我们现在需要把 Hoxton.SR1 换成 Hoxton.SR3 ,因此需要在hailtaxi-parent修改SpringCloud版本: ①我们可以为Feign接口创建一个降级处理的工厂对象,在工厂对象中处理程序异常降级处理方法,代码如下: @Component public class DriverFeignFallback implements FallbackFactory { @Override public DriverFeign create(Throwable throwable) { return new DriverFeign() { /** * status()降级处理方法 */ @Override public Driver status(String id, Integer status) { Driver driver = new Driver(); driver.setId(id); driver.setStatus(status); driver.setName("系统比较繁忙,请您稍后再试!"); return driver; } }; } }②我们还需要在Feign接口上添加 fallbackFactory 属性指定讲解处理的类,代码如下: |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |