Spring Cloud Alibaba Sentinel 熔断降级与OpenFeign整合

熔断降级

概述

对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。

重要的是:熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

熔断降级规则参数

熔断降级规则由 DegradeRule 对象定义,其主要参数如下:

Field说明默认值
resource资源名,即规则的作用对象
grade熔断策略,支持慢调用比例/异常比例/异常数策略慢调用比例
count慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值慢调用比例模式下,它表示以毫秒为单位的最大响应时间(RT)。
在异常比率模式中,它表示介于0.0和1.0之间的异常比率。
在异常计数模式下,它表示异常计数
timeWindow熔断时长,单位为 s默认为0,为0不会进入熔断
minRequestAmount熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入)5
statIntervalMs统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入)1000 ms
slowRatioThreshold慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)1.0D

熔断策略

grade 的取值有如下几种:

慢调用比例 (RuleConstant.DEGRADE_GRADE_RT值为0):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

异常比例 (RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO值为1):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

异常数 (RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT值为2):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

注意

异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效。为了统计异常比例或异常数,需要通过 Tracer.trace(ex) 记录业务异常。示例:

Entry entry = null;
try {
 entry = SphU.entry(resource);

 // Write your biz code here.
 // <<BIZ CODE>>
} catch (Throwable t) {
 if (!BlockException.isBlockException(t)) {
   Tracer.trace(t);
 }
} finally {
 if (entry != null) {
   entry.exit();
 }
}

开源整合模块,如 Sentinel Dubbo Adapter, Sentinel Web Servlet Filter 或 @SentinelResource 注解会自动统计业务异常,无需手动调用。

熔断降级事件监听

// name是监听的
EventObserverRegistry.getInstance().addStateChangeObserver("name",
    (prevState, newState, rule, snapshotValue) -> {
            // prevState:断路器的先前状态
            // newState:断路器的新状态
            // rule:关联规则
            // snapshotValue:断路器打开时的触发值(如果新状态为CLOSED或HALF_OPEN,则为空,反之新出发值为OPEN则有值)
    });

断路器的状态说明

  • OPEN:OPEN状态所有请求都将被拒绝。直到熔断时间结速。
  • HALF_OPEN:如果符合熔断规则,将进入OPEN状态,如果不符合熔断规则,则进入CLOSE状态
  • CLOSE:允许所有请求。

与OpenFeign整合

添加依赖

我们在上面说的,熔断降级一般在客户端使用,我们的OpenFeign其实就是客户端,Sentinel提供了对OpenFeign的注解的支持,只需引入相关依赖即可:

        <!-- 添加OpenFeign依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- 添加Sentinel依赖 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!-- 添加Sentinel DataSource Nacos依赖 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.8.6</version>
        </dependency>

增加配置

# 开启 Sentinel 对 Feign 的支持
feign.sentinel.enabled=true

此设置默认为false。即便设置了@FeignClient 的 fallback 也不会生效

OpenFeign 客户端示例

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

@FeignClient(value = "myCloud",fallback = SentinelFeignClient.Fallback.class)
public interface SentinelFeignClient {

    @RequestMapping("/myCloud/conf/getCommonConf")
    String getCommonConf();

    @Component
    class Fallback implements SentinelFeignClient{
        @Override
        public String getCommonConf() {
            return "熔断降级";
        }
    }

}

此示例请求了我们 Spring Cloud alibaba 使用Nacos服务发现 一文中的服务名为 myCloud 的 Provider 集群。

SentinelFeignClient.Fallback.class 为OpenFeign的熔断处理类,其实现规则如下:

  • 实现 @FeignClient 注解的接口
  • 实现接口的方法即为熔断时执行的方法。
  • @Component为必须的,是将Fallback 注册为Bean。
  • fallback还有FallbackFactory的方式来实现(此处不做讲解了)

此处我们除了添加fallback,好像没有定义资源。在Spring Boot 和 Spring Cloud 环境下Sentinel 会自动将我们的url定义为资源,所以我们可以不用使用@SentinelResource 来定义url接口为资源。

Feign 对应的接口中的资源名策略定义:httpmethod:protocol://requesturl。@FeignClient 注解中的所有属性,Sentinel 都做了兼容。我们上面的OpenFeign示例,资源名称对应为:GET:http://myCloud/myCloud/conf/getCommonConf

初始化配置持久化Rule规则

import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreaker;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.EventObserverRegistry;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.api.PropertyKeyConst;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;

@Component
public class SentinelRuleInit {

   @PostConstruct
   public void init(){
       Properties nacosPro = new Properties();
       nacosPro.put(PropertyKeyConst.SERVER_ADDR,"127.0.0.1:8848");

       // remoteAddress 代表 Nacos 服务端的地址
       // groupId 和 dataId 对应 Nacos 中相应配置
       ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource =
               new NacosDataSource<>(nacosPro, "Sentinel_Demo_Group", "com.yyoo.sentinel.demo.DegradeRule",
                       source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>(){}));
       DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());

       EventObserverRegistry.getInstance().addStateChangeObserver("logging",(prevState, newState, rule, snapshotValue)->{
           // prevState:断路器的先前状态
           // newState:断路器的新状态
           // rule:关联规则
           // snapshotValue:断路器打开时的触发值(如果新状态为CLOSED或HALF_OPEN,则为空)
           if(newState.equals(CircuitBreaker.State.OPEN)){
               System.out.println("断路器进入熔断状态");
           }else if(newState.equals(CircuitBreaker.State.HALF_OPEN)){
               System.out.println("断路器进入半熔断状态");
           }else if(newState.equals(CircuitBreaker.State.CLOSED)){
               System.out.println("断路器进入正常状态");
           }
       });
   }

}

Nacos中熔断规则的设置

[{
    "resource" : "GET:http://myCloud/myCloud/conf/getCommonConf",
    "grade": "2",
    "count": "5",
    "timeWindow":"10",
    "statIntervalMs":"60000"
},{
    "resource" : "GET:http://myCloud/myCloud/conf/getCommonConf",
    "grade": "0",
    "count": "2000",
    "timeWindow":"10",
    "statIntervalMs":"60000",
    "slowRatioThreshold":"0.8"
}]

在这里插入图片描述

此处我们为同一个资源设置了两个熔断规则配置

  1. 异常数模式,异常数达到5开启熔断,熔断时长为10s,统计时间为60000ms=1分钟
  2. 慢调用比例模式,RT超过2000ms视为慢调用,熔断时长为10s,统计时间为1分钟,慢调用比例超过80%开启熔断。

注:此处的熔断规则为我们的测试规则,在你的实际生产代码中请按你自己的应用需求进行相关设置。

验证示例

在Provider接口中抛出相应异常或者休眠足够的时长,即可验证我们示例中的两个熔断规则。详细的验证方案此处就不再赘述了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Cloud Alibaba提供了Sentinel作为熔断降级的解决方案。下面是使用Spring Cloud Alibaba进行熔断降级的步骤: 1. 添加依赖 在pom.xml中添加以下依赖: ```xml <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> ``` 2. 配置Sentinel 在application.properties或application.yml中添加以下配置: ```yaml spring.cloud.sentinel.transport.dashboard=localhost:8080 spring.cloud.sentinel.datasource.ds1.nacos.server-addr=localhost:8848 spring.cloud.sentinel.datasource.ds1.nacos.dataId=${spring.application.name}-sentinel spring.cloud.sentinel.datasource.ds1.nacos.groupId=DEFAULT_GROUP ``` 其中,`spring.cloud.sentinel.transport.dashboard`为Sentinel Dashboard的地址,`spring.cloud.sentinel.datasource.ds1.nacos.server-addr`为Nacos服务的地址,`spring.cloud.sentinel.datasource.ds1.nacos.dataId`为Sentinel规则持久化在Nacos上的Data ID。 3. 编写熔断降级规则 在Sentinel Dashboard中编写熔断降级规则,例如: - 熔断规则:当QPS超过阈值时,进行熔断 - 降级规则:当服务出现异常时,进行降级处理 4. 使用@SentinelResource注解 在需要进行熔断降级的方法上使用@SentinelResource注解,例如: ```java @SentinelResource(value = "hello", fallback = "fallback") public String hello() { // ... } public String fallback() { // ... } ``` 其中,value为资源名称,fallback为降级处理的方法名。 这样,当资源名称为hello的方法发生熔断降级时,会自动调用fallback方法进行处理。 5. 启动应用 启动应用后,可以在Sentinel Dashboard中查看实时的熔断降级信息和统计数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值