一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring Cloud 中斷路器 Circuit Breaker的應用

Spring Cloud 中斷路器 Circuit Breaker的應用

2021-12-15 23:01Spring源碼解讀 Java教程

SpringCloud Circuit breaker(斷路器)提供了跨不同斷路器實現的抽象。它提供了在應用程序中使用的一致API,允許開發人員選擇最適合應用程序需要的斷路器實現。

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的一個非常簡單的示例:

  1. @Service
  2. public static class DemoService {
  3. private RestTemplate rest;
  4. private CircuitBreakerFactory cbFactory;
  5. public DemoService(RestTemplate rest, CircuitBreakerFactory cbFactory) {
  6. this.rest = rest;
  7. this.cbFactory = cbFactory;
  8. }
  9. public String slow() {
  10. // 通過默認的CircuitBreakerFactory工廠創建一個指定id(名稱)的斷路器
  11. // run方法是實際執行你的業務方法,第二個參數throwable 是當發生異常或者是執行超時
  12. // 執行的回退(降級)處理
  13. return cbFactory.create("slow").run(() -> rest.getForObject("/slow", String.class), throwable -> "fallback");
  14. }
  15. }

項目配置

通過引入下面不同依賴來確定使用具體的那個斷路器

  • 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為例來使用

引入依賴

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

定義具有熔斷功能的服務

  1. @Service
  2. public class DemoService {
  3. private RestTemplate rest;
  4. // 注入系統默認的實現
  5. private CircuitBreakerFactory cbFactory;
  6. public DemoService(RestTemplate rest, CircuitBreakerFactory cbFactory) {
  7. this.rest = rest;
  8. this.cbFactory = cbFactory;
  9. }
  10. public String slow() {
  11. // 使用系統默認的實現創建斷路器進行業務的處理
  12. return cbFactory.create("slow").run(() -> rest.getForObject("http://localhost:8080/demos/slow", String.class), throwable -> "fallback");
  13. }
  14. public String slow2() {
  15. // 使用自定義的斷路器工廠進行業務的處理
  16. return cbf().create("demo-slow").run(() -> rest.getForObject("http://localhost:8080/demos/slow", String.class), throwable -> "fallback");
  17. }
  18. // 可以將這個定義為Bean來覆蓋系統默認的實現,在系統默認的實現上有條件限定
  19. private CircuitBreakerFactory cbf() {
  20. HystrixCircuitBreakerFactory cbf = new HystrixCircuitBreakerFactory() ;
  21. // 配置線程池
  22. HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter() ;
  23. threadPoolProperties.withCoreSize(5)
  24. .withKeepAliveTimeMinutes(5)
  25. .withMaxQueueSize(Integer.MAX_VALUE)
  26. .withQueueSizeRejectionThreshold(1000) ;
  27. // 配置默認的執行行為屬性
  28. HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter() ;
  29. commandProperties.withCircuitBreakerEnabled(true)
  30. // 當請求超過了3s那么斷路器就會工作進行回退(降級處理),執行上面run方法中的第二個參數
  31. .withExecutionTimeoutInMilliseconds(3000)
  32. .withRequestCacheEnabled(true)
  33. // 隔離策略有兩種THREAD,SEMAPHORE
  34. // THREAD: 避免線程被阻塞
  35. // SEMAPHORE: 適合高并發限流處理;因為線程池的方式一般不會創建過多的線程
  36. // 線程是有限的,在高并發情況下是沒法滿足響應處理的。
  37. .withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD);
  38. // 將其加入到集合中,為不同的服務創建不同的配置
  39. cbf.configure(builder -> {
  40. builder.commandProperties(commandProperties).groupName("demo") ;
  41. }, "demo-slow");
  42. // 當默認的id不存在時使用這默認的配置
  43. cbf.configureDefault(id -> {
  44. HystrixCommand.Setter setter = HystrixCommand.Setter
  45. .withGroupKey(HystrixCommandGroupKey.Factory.asKey("demo")) // 服務分組,大的模塊
  46. .andCommandKey(HystrixCommandKey.Factory.asKey("demo-slow")) // 服務標識(具體服務分組中的某一個子的服務),子模塊
  47. .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("demo-pools")) // 線程池名稱
  48. .andThreadPoolPropertiesDefaults(threadPoolProperties) // 線程池相關配置
  49. .andCommandPropertiesDefaults(commandProperties) ; // 執行時相關屬性配置
  50. return setter ;
  51. });
  52. return cbf ;
  53. }
  54. }

Controller接口

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

原理

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);
  17. }

斷路器具體的子類實現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. }
  18. }

斷路器工廠有了,接下來就是通過工廠創建具體的斷路器對象了

通過上面的代碼執行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. }
  11. }

上面創建的是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. }
  21. }

原文鏈接:https://www.toutiao.com/a7036197230167982630/

延伸 · 閱讀

精彩推薦
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
主站蜘蛛池模板: 日本女人www | 四虎b7s22c0m| 四虎最新紧急更新地址 | 四虎影视在线永久免费观看 | 精品久久久久久久久久香蕉 | 天天躁天天碰天天看 | 全肉一女n男np高h乳 | 国产免费午夜高清 | 操人网| 91精品国产91热久久久久福利 | 12345国产精品高清在线 | 日本视频中文字幕 | 免费观看www视频 | avtt天堂在线 | 精品一区二区三区五区六区七区 | 色婷婷狠狠 | 欧美一区二区三区gg高清影视 | 白白国产永久免费视频 | 好湿好紧太硬了我好爽 | 亚洲视频一| 四虎影院在线免费观看 | 狠狠撸在线播放 | 国产精品久久久久久久久齐齐 | 天堂中文在线免费观看 | 国产一级毛片潘金莲的奶头 | 学校女性奴sm训练调教 | 人与动人物aaaa | free极度另类性欧美 | 四虎影剧院 | 精彩国产萝视频在线 | 好大好爽好舒服视频 | 日本免费v片一二三区 | 丁香五香天堂网 | 国产专区视频在线观看 | 人与善交大片免费看 | 亚洲高清一区二区三区四区 | 亚洲天堂导航 | 情欲满载2012美国dvd | 91制片厂果冻传媒杨柳作品 | 精品免费国产 | 热99精品视频 |