文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Cloud 中断路器 Circuit Breaker的应用

2024-12-02 12:55

关注

环境: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的一个非常简单的示例:

  1. @Service 
  2. public static class DemoService { 
  3.   private RestTemplate rest; 
  4.   private CircuitBreakerFactory cbFactory; 
  5.  
  6.   public DemoService(RestTemplate rest, CircuitBreakerFactory cbFactory) { 
  7.     this.rest = rest; 
  8.     this.cbFactory = cbFactory; 
  9.   } 
  10.  
  11.   public String slow() { 
  12.     // 通过默认的CircuitBreakerFactory工厂创建一个指定id(名称)的断路器 
  13.     // run方法是实际执行你的业务方法,第二个参数throwable 是当发生异常或者是执行超时 
  14.     // 执行的回退(降级)处理 
  15.     return cbFactory.create("slow").run(() -> rest.getForObject("/slow", String.class), throwable -> "fallback"); 
  16.   } 

项目配置

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

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

示例

这里以Hystrix为例来使用

引入依赖

  1.  
  2.   org.springframework.cloud 
  3.   spring-cloud-starter-netflix-hystrix 
  4.   2.2.10.RELEASE 
  5.  

定义具有熔断功能的服务

  1. @Service 
  2. public class DemoService { 
  3.  
  4.   private RestTemplate rest; 
  5.   // 注入系统默认的实现 
  6.   private CircuitBreakerFactory cbFactory; 
  7.  
  8.   public DemoService(RestTemplate rest, CircuitBreakerFactory cbFactory) { 
  9.     this.rest = rest; 
  10.     this.cbFactory = cbFactory; 
  11.   } 
  12.  
  13.   public String slow() { 
  14.     // 使用系统默认的实现创建断路器进行业务的处理 
  15.     return cbFactory.create("slow").run(() -> rest.getForObject("http://localhost:8080/demos/slow", String.class), throwable -> "fallback"); 
  16.   } 
  17.  
  18.   public String slow2() { 
  19.     // 使用自定义的断路器工厂进行业务的处理 
  20.     return cbf().create("demo-slow").run(() -> rest.getForObject("http://localhost:8080/demos/slow", String.class), throwable -> "fallback"); 
  21.   } 
  22.  
  23.   // 可以将这个定义为Bean来覆盖系统默认的实现,在系统默认的实现上有条件限定 
  24.   private CircuitBreakerFactory cbf() { 
  25.     HystrixCircuitBreakerFactory cbf = new HystrixCircuitBreakerFactory() ; 
  26.     // 配置线程池 
  27.     HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter() ; 
  28.     threadPoolProperties.withCoreSize(5) 
  29.       .withKeepAliveTimeMinutes(5) 
  30.       .withMaxQueueSize(Integer.MAX_VALUE) 
  31.       .withQueueSizeRejectionThreshold(1000) ; 
  32.     // 配置默认的执行行为属性 
  33.     HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter() ; 
  34.     commandProperties.withCircuitBreakerEnabled(true
  35.     // 当请求超过了3s那么断路器就会工作进行回退(降级处理),执行上面run方法中的第二个参数 
  36.       .withExecutionTimeoutInMilliseconds(3000) 
  37.       .withRequestCacheEnabled(true
  38.       // 隔离策略有两种THREAD,SEMAPHORE 
  39.       // THREAD: 避免线程被阻塞 
  40.       // SEMAPHORE: 适合高并发限流处理;因为线程池的方式一般不会创建过多的线程 
  41.       // 线程是有限的,在高并发情况下是没法满足响应处理的。 
  42.       .withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD); 
  43.          
  44.     // 将其加入到集合中,为不同的服务创建不同的配置 
  45.     cbf.configure(builder -> { 
  46.       builder.commandProperties(commandProperties).groupName("demo") ; 
  47.     }, "demo-slow"); 
  48.          
  49.     // 当默认的id不存在时使用这默认的配置 
  50.     cbf.configureDefault(id -> { 
  51.       HystrixCommand.Setter setter = HystrixCommand.Setter 
  52.         .withGroupKey(HystrixCommandGroupKey.Factory.asKey("demo")) // 服务分组,大的模块 
  53.         .andCommandKey(HystrixCommandKey.Factory.asKey("demo-slow")) // 服务标识(具体服务分组中的某一个子的服务),子模块 
  54.         .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("demo-pools")) // 线程池名称 
  55.         .andThreadPoolPropertiesDefaults(threadPoolProperties) // 线程池相关配置 
  56.         .andCommandPropertiesDefaults(commandProperties) ; // 执行时相关属性配置  
  57.       return setter ; 
  58.     }); 
  59.     return cbf ; 
  60.   } 
  61.  

Controller接口

  1. @RestController 
  2. @RequestMapping("/demos"
  3. public class DemoController { 
  4.      
  5.   @Resource 
  6.   private DemoService demoService ; 
  7.      
  8.   @GetMapping("/index"
  9.   public Object index() { 
  10.     return demoService.slow2() ; 
  11.   } 
  12.      
  13.   @GetMapping("/slow"
  14.   public Object slow() { 
  15.     try { 
  16.       TimeUnit.SECONDS.sleep(5) ; 
  17.     } catch (InterruptedException e) { 
  18.       e.printStackTrace(); 
  19.     } 
  20.     return "slow" ; 
  21.   } 
  22.      

原理

CircuitBreakerFactory#create方法创建了CircuitBreaker实例

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

HystrixCircuitBreakerFactory类

  1. public class HystrixCircuitBreakerFactory extends CircuitBreakerFactory { 

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

当执行HystrixCircuitBreakerFactory#configure方法时:

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

断路器具体的子类实现HystrixCircuitBreakerFactory

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

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

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

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

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

  1. public class HystrixCircuitBreaker implements CircuitBreaker { 
  2.   private HystrixCommand.Setter setter; 
  3.   public HystrixCircuitBreaker(HystrixCommand.Setter setter) { 
  4.     this.setter = setter; 
  5.   } 
  6.   @Override 
  7.   public  T run(Supplier toRun, Function fallback) { 
  8.     // 最终执行的就是Hystrix的核心 HystrixCommand对象 
  9.     HystrixCommand command = new HystrixCommand(setter) { 
  10.       @Override 
  11.       protected T run() throws Exception { 
  12.         return toRun.get(); 
  13.       } 
  14.       @Override 
  15.       protected T getFallback() { 
  16.         return fallback.apply(getExecutionException()); 
  17.       } 
  18.     }; 
  19.     return command.execute(); 
  20.   } 

 

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯