Spring Cloud 中断路器 Circuit Breaker的应用

环境:Springboot2.3.12.RELEASE + cloud-netflix-hystrix2.2.10.RELEASE


简介

SpringCloud Circuit breaker(断路器)提供了跨不同断路器实现的抽象。它提供了在应用程序中使用的一致API,允许开发人员选择最适合应用程序需要的断路器实现。

支持的断路器类型:

核心概念

要在代码中创建断路器(circuit breaker),可以使用断路器工厂API。当您在类路径中包含Spring Cloud Circuit Breaker starter时,将自动创建一个实现此API的bean。下面给出了使用此API的一个非常简单的示例:

@Service
public static class DemoService {
  private RestTemplate rest;
  private CircuitBreakerFactory cbFactory;

  public DemoService(RestTemplate rest, CircuitBreakerFactory cbFactory) {
    this.rest = rest;
    this.cbFactory = cbFactory;
  }

  public String slow() {
    // 通过默认的CircuitBreakerFactory工厂创建一个指定id(名称)的断路器
    // run方法是实际执行你的业务方法,第二个参数throwable 是当发生异常或者是执行超时
    // 执行的回退(降级)处理
    return cbFactory.create("slow").run(() -> rest.getForObject("/slow", String.class), throwable -> "fallback");
  }
}

项目配置

通过引入下面不同依赖来确定使用具体的那个断路器

以上5种断路器是不同的实现方式,根据需要引入即可。

示例

这里以Hystrix为例来使用

引入依赖


  org.springframework.cloud
  spring-cloud-starter-netflix-hystrix
  2.2.10.RELEASE

定义具有熔断功能的服务

@Service
public class DemoService {

  private RestTemplate rest;
  // 注入系统默认的实现
  private CircuitBreakerFactory cbFactory;

  public DemoService(RestTemplate rest, CircuitBreakerFactory cbFactory) {
    this.rest = rest;
    this.cbFactory = cbFactory;
  }

  public String slow() {
    // 使用系统默认的实现创建断路器进行业务的处理
    return cbFactory.create("slow").run(() -> rest.getForObject("http://localhost:8080/demos/slow", String.class), throwable -> "fallback");
  }

  public String slow2() {
    // 使用自定义的断路器工厂进行业务的处理
    return cbf().create("demo-slow").run(() -> rest.getForObject("http://localhost:8080/demos/slow", String.class), throwable -> "fallback");
  }

  // 可以将这个定义为Bean来覆盖系统默认的实现,在系统默认的实现上有条件限定
  private CircuitBreakerFactory cbf() {
    HystrixCircuitBreakerFactory cbf = new HystrixCircuitBreakerFactory() ;
    // 配置线程池
    HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter() ;
    threadPoolProperties.withCoreSize(5)
      .withKeepAliveTimeMinutes(5)
      .withMaxQueueSize(Integer.MAX_VALUE)
      .withQueueSizeRejectionThreshold(1000) ;
    // 配置默认的执行行为属性
    HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter() ;
    commandProperties.withCircuitBreakerEnabled(true)
    // 当请求超过了3s那么断路器就会工作进行回退(降级处理),执行上面run方法中的第二个参数
      .withExecutionTimeoutInMilliseconds(3000)
      .withRequestCacheEnabled(true)
      // 隔离策略有两种THREAD,SEMAPHORE
      // THREAD: 避免线程被阻塞
      // SEMAPHORE: 适合高并发限流处理;因为线程池的方式一般不会创建过多的线程
      // 线程是有限的,在高并发情况下是没法满足响应处理的。
      .withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD);
		
    // 将其加入到集合中,为不同的服务创建不同的配置
    cbf.configure(builder -> {
      builder.commandProperties(commandProperties).groupName("demo") ;
    }, "demo-slow");
	    
    // 当默认的id不存在时使用这默认的配置
    cbf.configureDefault(id -> {
      HystrixCommand.Setter setter = HystrixCommand.Setter
        .withGroupKey(HystrixCommandGroupKey.Factory.asKey("demo")) // 服务分组,大的模块
        .andCommandKey(HystrixCommandKey.Factory.asKey("demo-slow")) // 服务标识(具体服务分组中的某一个子的服务),子模块
        .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("demo-pools")) // 线程池名称
        .andThreadPoolPropertiesDefaults(threadPoolProperties) // 线程池相关配置
        .andCommandPropertiesDefaults(commandProperties) ; // 执行时相关属性配置 
      return setter ;
    });
    return cbf ;
  }

}

Controller接口

@RestController
@RequestMapping("/demos")
public class DemoController {
	
  @Resource
  private DemoService demoService ;
	
  @GetMapping("/index")
  public Object index() {
    return demoService.slow2() ;
  }
	
  @GetMapping("/slow")
  public Object slow() {
    try {
      TimeUnit.SECONDS.sleep(5) ;
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return "slow" ;
  }
	
}

原理

CircuitBreakerFactory#create方法创建了CircuitBreaker实例

根据当前的CLASSPATH我们使用的是Hystrix,那么这里使用的工厂就是:

HystrixCircuitBreakerFactory类

public class HystrixCircuitBreakerFactory extends CircuitBreakerFactory {

泛型参数:Setter就是用来配置Hystrix相关配置信息的(这里主要用来CommandKey与Setter进行绑定),HystrixConfigBuilder用来构建 HystrixCommand.Setter对象。

当执行HystrixCircuitBreakerFactory#configure方法时:

public abstract class AbstractCircuitBreakerFactory> {
  private final ConcurrentHashMap configurations = new ConcurrentHashMap<>();
  public void configure(Consumer consumer, String... ids) {
    for (String id : ids) {
      // 构建一个Builder对象
      CONFB builder = configBuilder(id);
      // 这里通过builder(HystrixConfigBuilder)对象来应用Consumer中编写的配置信息
      consumer.accept(builder);
      // 构建HystrixCommand.Setter 对象
      CONF conf = builder.build();
      // 最后将通过id 与 Setter对象绑定key=value存入Map集合中
      getConfigurations().put(id, conf);
    }
  }
  // 该方法在子类HystrixCircuitBreakerFactory中实现
  protected abstract CONFB configBuilder(String id);
}

断路器具体的子类实现HystrixCircuitBreakerFactory

// 子类继承的父类中的泛型:第一个泛型参数:需要构建什么样的一个配置,第二个泛型参数:通过谁来构建第一个泛型参数配置
public class HystrixCircuitBreakerFactory extends CircuitBreakerFactory {
  public HystrixConfigBuilder configBuilder(String id) {
    return new HystrixConfigBuilder(id);
  }
  public static class HystrixConfigBuilder extends AbstractHystrixConfigBuilder {
    public HystrixConfigBuilder(String id) {
      super(id);
    }
    // 从这里也看出来最终Builder就是用来构建Setter对象用
    @Override
    public HystrixCommand.Setter build() {
      return HystrixCommand.Setter.withGroupKey(getGroupKey())
        .andCommandKey(getCommandKey())
        .andCommandPropertiesDefaults(getCommandPropertiesSetter());
    }
  }
}

断路器工厂有了,接下来就是通过工厂创建具体的断路器对象了

通过上面的代码执行cbf().create("demo-slow")方法时执行了什么?

public class HystrixCircuitBreakerFactory extends CircuitBreakerFactory {
  private Function defaultConfiguration = id -> HystrixCommand.Setter
    .withGroupKey(HystrixCommandGroupKey.Factory.asKey(getClass().getSimpleName()))
    .andCommandKey(HystrixCommandKey.Factory.asKey(id));
  public HystrixCircuitBreaker create(String id) {
    // 通过上面分析最终所有的Hystrix的Setter会与id绑定存入一个Map中
    // 这里computeIfAbsent方法先从集合中通过id获取,如果获取不到则将第二个参数存入集合中返回
    HystrixCommand.Setter setter = getConfigurations().computeIfAbsent(id, defaultConfiguration);
    return new HystrixCircuitBreaker(setter);
  }
}

上面创建的是HystrixCircuitBreaker断路器,当执行run方法时:

public class HystrixCircuitBreaker implements CircuitBreaker {
  private HystrixCommand.Setter setter;
  public HystrixCircuitBreaker(HystrixCommand.Setter setter) {
    this.setter = setter;
  }
  @Override
  public  T run(Supplier toRun, Function fallback) {
    // 最终执行的就是Hystrix的核心 HystrixCommand对象
    HystrixCommand command = new HystrixCommand(setter) {
      @Override
      protected T run() throws Exception {
        return toRun.get();
      }
      @Override
      protected T getFallback() {
        return fallback.apply(getExecutionException());
      }
    };
    return command.execute();
  }
}

完毕!!!

关注+转发

Sentinel 与 Hystrix 的对比

SpringCloud Hystrix实现资源隔离应用

SpringCloud Gateway 应用Hystrix 限流功能 自定义Filter详解

Spring Boot Security防重登录及在线总数

Spring Retry重试框架的应用

springboot mybatis jpa 实现读写分离

Spring容器对象BeanFactory与ApplicationContext你都清楚了吗?

Spring Cloud 中断路器 Circuit Breaker的应用

Spring Cloud 中断路器 Circuit Breaker的应用

Spring Cloud 中断路器 Circuit Breaker的应用

Spring Cloud 中断路器 Circuit Breaker的应用

展开阅读全文

页面更新:2024-04-27

标签:断路器   子类   线程   绑定   对象   工厂   参数   业务   方法   系统

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top