Spring Cloud 中断路器 Circuit Breaker 的应用

环境:Springboot2.3.12.RELEASE +

cloud-netflix-hystrix2.2.10.RELEASE

简介

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

支持的应用断路器类型:

Netfix Hystrix Resilience4J Sentinel Spring Retry

核心概念

要在代码中创建断路器(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");   } } 

项目配置

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

Hystrix - org.springframework.cloud:spring-cloud-starter-netflix-hystrix Resilience4J - org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j Reactive Resilience4J - org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j Spring Retry - org.springframework.cloud:spring-cloud-starter-circuitbreaker-spring-retry Sentinal - org.springframework.cloud:spring-cloud-starter-circuitbreaker-sentinal

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

示例

这里以Hystrix为例来使用

引入依赖

<dependency>   <groupId>org.springframework.cloud</groupId>   <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>   <version>2.2.10.RELEASE</version> </dependency> 

定义具有熔断功能的断路服务

@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<HystrixCommand.Setter, HystrixCircuitBreakerFactory.HystrixConfigBuilder> 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<HystrixCommand.Setter, HystrixCircuitBreakerFactory.HystrixConfigBuilder> {  

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

当执行HystrixCircuitBreakerFactory#configure方法时:

public abstract class AbstractCircuitBreakerFactory<CONF, CONFB extends ConfigBuilder<CONF>> {    private final ConcurrentHashMap<String, CONF> configurations = new ConcurrentHashMap<>();   public void configure(Consumer<CONFB> 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<HystrixCommand.Setter, HystrixCircuitBreakerFactory.HystrixConfigBuilder> {    public HystrixConfigBuilder configBuilder(String id) {      return new HystrixConfigBuilder(id);   }   public static class HystrixConfigBuilder extends AbstractHystrixConfigBuilder<HystrixCommand.Setter> {      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<HystrixCommand.Setter, HystrixCircuitBreakerFactory.HystrixConfigBuilder> {    private Function<String, HystrixCommand.Setter> 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> T run(Supplier<T> toRun, Function<Throwable, T> fallback) {      // 最终执行的就是Hystrix的核心 HystrixCommand对象     HystrixCommand<T> command = new HystrixCommand<T>(setter) {        @Override       protected T run() throws Exception {          return toRun.get();       }       @Override       protected T getFallback() {          return fallback.apply(getExecutionException());       }     };     return command.execute();   } } 亿华云
人工智能
上一篇:数据中心为了提高物理安全性需要提高设备互操作性
下一篇:在中国,为中国——西门子低代码精准助力本土企业数字化探索之路