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

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

引入依賴

org。springframework。cloud spring-cloud-starter-netflix-hystrix 2。2。10。RELEASE

定義具有熔斷功能的服務

@Servicepublic 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的應用