Spring Cloud 2021.0.1 实践 Resilience4J

Offer 驾到,掘友接招!我正在参与2022春招系列活动-Debug实录任务,点击查看活动详情

Spring Cloud CircuitBreaker 提供了跨不同断路器实现的抽象。它提供了在您的应用程序中使用的一致 API,让您(开发人员)选择最适合您的应用程序需求的断路器实现。

Spring Cloud CircuitBreaker 项目包含 Resilience4J 和 Spring Retry 的实现。Spring Cloud CircuitBreaker 中实现的 API 位于 Spring Cloud Commons 中。

Spring Cloud 支持一下几种 CircuitBreaker

  • Resilience4J
  • Sentinel
  • Spring Retry

下文主要描述 Resilience4J 的使用

Resilience4J 介绍

Resilience4J 其实是参照 Netfix Hystrix 实现的的断路器

断路器 本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似保险熔断),向调用方法返回一个符合预期的,可处理的被选相应(FallBack), 而不是长时间的等待或者跑出调用方法无法处理的异常,这样就保证了服务调用方的线程不会长时间,不必要地占用,从而避免了故障在分布式系统中进行蔓延,从而导致雪崩效应。

Resilience4J 实现有两种 starter,一种用于 reactor 方式的依赖,另一种用于非 reactor 的 starter

依赖如下:

  • org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j 普通模式

  • org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j reactor 模式

reactor 模式的依赖可以配合 spring cloud gateway 使用

使用配置

默认配置

要为所有断路器提供默认配置,我们需要创建一个自定义 bean,该 bean被传递给Resilience4JCuitBreakerFactory 或 ReactiveResilience4JCuitBreakerFactory。configureDefault 方法可用于提供默认配置。

    @Bean
    public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
        return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
                // 默认超时时间 4s
                .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(4)).build())
                // circuitBreaker 使用默认配置
                .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
                .build());
    }
复制代码

基于 YML 方式的配置

下面是断路器和时间限流配配置:

# 断路器配置
resilience4j.circuitbreaker:
 instances:
 	   # 配置服务
     backendA:
         registerHealthIndicator: true
         slidingWindowSize: 100
     backendB:
         registerHealthIndicator: true
				 # 滑动窗口类型:COUNT_BASED 基于计数的滑动窗口, TIME_BASED 基于计时的滑动窗口
				 slidingWindowType: TIME_BASED
         # 滑动窗口大小
         slidingWindowSize: 10
         # 当 circuitbreaker 处于 HalfOpen 允许通过的请求数量
         permittedNumberOfCallsInHalfOpenState: 3
         recordFailurePredicate: io.github.robwin.exception.RecordFailurePredicate

# 时间限流
resilience4j.timelimiter:
 instances:
     backendA:
         timeoutDuration: 2s
         cancelRunningFuture: true
     backendB:
         timeoutDuration: 1s
         cancelRunningFuture: false
复制代码

Bulkhead 配置

Bulkhead作用是让一个应用中不同方法互不影响,避免某些方法调用异常危及整个应用。

Java 方式的配置

@Bean
public Customizer<Resilience4jBulkheadProvider> slowBulkheadProviderCustomizer() {
    return provider -> provider.configure(builder -> builder
        .bulkheadConfig(BulkheadConfig.custom().maxConcurrentCalls(1).build())
        .threadPoolBulkheadConfig(ThreadPoolBulkheadConfig.ofDefaults()), "slowBulkhead");
}
复制代码

YML 方式的配置

resilience4j.thread-pool-bulkhead:
    instances:
        backendA:
            # 配置最大线程数
            maxThreadPoolSize: 1
            # 核心线程数
            coreThreadPoolSize: 1
resilience4j.bulkhead:
    instances:
        backendB:
            maxConcurrentCalls: 10
复制代码

举个例子

首先我们下先加入 gradle 的依赖

implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'
复制代码

我们需要配置 feign 使用 circuitbreaker yml 配置文件如下:

feign:
  circuitbreaker:
    enabled: true
      
resilience4j.timelimiter:
 instances:
     default:
         timeoutDuration: 1s
         cancelRunningFuture: true      
复制代码

如果通过 Fegin 调用 payment-service 服务 /payment/create feign 代码如下:

@FeignClient(name = "payment-service", path = "/payment")
public interface PaymentFeign {

    @PostMapping("/create")
    PaymentVo create(@RequestBody @Validated PaymentDto paymentDto);
}
复制代码

如果超时会出现一下错误:

image-20220317232136970.png

参考文档

Guess you like

Origin juejin.im/post/7076094126474657828