【Spring Cloud】 CircuitBreaker 组件 resilience4j 二

前言

上章节了解了 resilience4j 的单独使用方法,同样它也可以完美契合 Spring(SpringBoot ...),对此 resilience4j 官方提供了 resilience4j-springresilience4j-spring-boot2 两个 module

当然还有 resilience4j-spring-cloud,本文略

SpringBoot 下的使用

resilience4j-spring

spring

如图,resilience4j-spring 模块主要提供这些功能(以 CircuitBreaker 组件示例,其他基本雷同)

  • Aspect 切面逻辑,首先我们肯定不想手工 coding 去装饰一个个客户端请求,因此注解形式的声明可以大大降低工作量且更加 Spring,其中的注解、逻辑相关都有此类提供,熔断组件的声明注解即 @CircuitBreaker
  • 核心配置类,提供核心组件类诸如 CircuitBreakerRegistry 等的装配
  • ConfigurationProperties 的提供,这是我们通过配置文件进行组件属性配置的核心,根据此配置 Spring 就可以帮我们创建相应的组件

可以看到 resilience4j-spring 基本提供了所有我们想要的功能

resilience4j-spring-boot2

到了 SpringBoot 要干的活就不多了,它提供了多组自动装配类,使得我们可以 “零” 配置去使用 resilience4j 组件,直接看示例,同时基于注解的声明要用到 Spring AOP,因此需要引入对应依赖 spring-boot-starter-aop

application.yaml

# bulkhead(基于信号量)
resilience4j.bulkhead:
  instances:
    delay:
      maxConcurrentCalls: 1

# ThreadPoolBulkhead
resilience4j.thread-pool-bulkhead:
  instances:
    delay:
      maxThreadPoolSize: 1
      coreThreadPoolSize: 1
      queueCapacity: 1

# TimeLimter
resilience4j.timelimiter:
  instances:
    delay:
      timeoutDuration: 1s

# RateLimiter
resilience4j.ratelimiter:
  instances:
    delay:
      timeoutDuration: 0
      limitRefreshPeriod: 3s
      limitForPeriod: 2

# CircuitBreaker
resilience4j.circuitbreaker:
  instances:
    delay:
      failureRateThreshold: 50
      slowCallRateThreshold: 100
      slowCallDurationThreshold: 500ms
      minimumNumberOfCalls: 2
      waitDurationInOpenState: 60s
      recordExceptions:
        - com.xsn.circuitbreaker.resilience4j.exception.MyException

# Retry
resilience4j.retry:
  instances:
    delay:
      maxAttempts: 2
      waitDuration: 500ms
      retryExceptions:
        - com.xsn.circuitbreaker.resilience4j.exception.MyException
      failAfterMaxRetries: true

配置项不难理解,如上我们声明了一组 name: delay 的组件

值得一提的是,切面是有优先级的,默认:Retry ( CircuitBreaker ( RateLimiter ( TimeLimiter ( Bulkhead ( Function ) ) ) ) ),当然也可以通过属性修改优先级如下(数字越大优先级越高):

resilience4j:
  circuitbreaker:
    circuitBreakerAspectOrder: 1
  retry:
    retryAspectOrder: 2

Decorate Function

	@Bulkhead(name = "delay")
    @RateLimiter(name = "delay", fallbackMethod = "rateLimiterFallback")
    @CircuitBreaker(name = "delay")
    @Retry(name = "delay")
    @RequestMapping(value = "/delay", method = RequestMethod.GET)
    public String delay(@RequestParam("time") int time) {

        System.out.println("invoke ...");
        return restTemplate.getForObject(
                "http://EUREKA-CLIENT-1/delay?time=" + time
                , String.class
        );
    }

    public String rateLimiterFallback(int time, Throwable e) {

        return MessageFormat.format(
                "rate out, param: {0}, e: {1}"
                , time, e.getMessage()
        );
    }

直接基于注解声明,比之前手工编码方便多了,其中 rateLimiterFallback 作为 RateLimiter 组件的回调,其参数(类型)要保持与目标方法完全相同,且多出的 Throwable 可以用来处理异常逻辑

同时,如果要使用 ThreadPoolBulkheadTimeLimiter 组件,返回类型必须为 CompletionStageFuture,如下:

	@Bulkhead(name = "delay", type = Bulkhead.Type.THREADPOOL)
    @RequestMapping(value = "/delayThread", method = RequestMethod.GET)
    public CompletableFuture<String> delayThread(@RequestParam("time") int time) {

        System.out.println("invoke ...");
        Supplier<String> supplier = () -> restTemplate.getForObject(
                "http://EUREKA-CLIENT-1/delay?time=" + time
                , String.class
        );
        return CompletableFuture.supplyAsync(supplier);
    }

小结

以上可以理解为 resilience4jSpringBoot 中的使用,当然核心功能基本由 resilience4j-spring 提供,相对于编码方式这种使用就很轻松了

接下来我想聊一下 spring-cloud-circuitBreaker-resilience4j

SpringCloud 下的使用

spring-cloud-circuitBreaker-resilience4j 是这样一个项目:基于 resilience4j 实现 SpringCloud熔断 组件功能,它提供了一个基于 spring-cloud-commons熔断 抽象 CircuitBreakerFactory 的实现 Resilience4JCircuitBreakerFactory

spring-cloud
同时,它的依赖中也是包含 resilience4j-spring-boot2
pom

resilience4j-spring-boot2 由 resilience4j 官方实现
spring-cloud-circuitbreaker-resilience4j 由 SpringCloud 官方实现
,同时还提供有其他实现诸如:spring-cloud-circuitbreaker-spring-retry 等 

因此,在 SpringCloud 虽然也是可以基于注解、配置文件去声明、使用所有 resilience4j 组件(使用注解也是需要 aop 的),但本质其实与 spring-cloud-circuitbreaker-resilience4j 无关,真正与 SpringCloud 有关的是 Resilience4JCircuiBreakerFactory Resilience4JCircuiBreaker 等实例的使用,后者仅侧重于 resilience4jCircuitBreaker TimeLimter Bulkhead(ThreadPoolBulkhead) 组件使用

相关的实现细节还是十分巧妙的,不多赘述,直接上示例

示例

@RestController
public class SCStyleController {

    @Configuration
    static class Config {

        /**
         * 通过 Resilience4JCircuitBreakerFactory 可以定制
         *      CircuitBreaker TimeLimiter 组件
         * @return
         */
        @Bean
        public Customizer<Resilience4JCircuitBreakerFactory> circuitBreakerFactoryCustomizer1() {
            return factory -> factory.configureDefault(
                    id -> new Resilience4JConfigBuilder(id)
                            .circuitBreakerConfig(
                                    CircuitBreakerConfig
                                            .custom()
                                            .slowCallDurationThreshold(Duration.ofSeconds(1))
                                            .slowCallRateThreshold(50)
                                            .minimumNumberOfCalls(4)
                                            .build()
                            )
                            .timeLimiterConfig(
                                    TimeLimiterConfig
                                            .custom()
                                            .timeoutDuration(Duration.ofSeconds(3))
                                            .build()
                            )
                            .build()
            );
        }

        /**
         * 通过 Resilience4jBulkheadProvider 可以定制 Bulkhead
         *      ThreadPoolBulkhead 组件
         * @return
         */
        @Bean
        public Customizer<Resilience4jBulkheadProvider> resilience4jBulkheadProviderCustomizer1() {

            return provider -> provider.configure(
                    builder -> builder
                            .threadPoolBulkheadConfig(
                                    ThreadPoolBulkheadConfig
                                            .custom()
                                            .maxThreadPoolSize(4)
                                            .coreThreadPoolSize(2)
                                            .queueCapacity(2)
                                            .build()
                            )
                    , "delay"
            );
        }
    }

    @Autowired
    CircuitBreakerFactory circuitBreakerFactory;

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping(value = "scDelay", method = RequestMethod.GET)
    public String scDelay(@RequestParam(value = "time") int time) {

        /**
         * 通过 circuitBreakerFactory 创建 Resilience4JCircuitBreaker
         *      实例
         */
        return circuitBreakerFactory
                .create("delay")
                .run(() -> restTemplate.getForObject(
                        "http://EUREKA-CLIENT-1/delay?time=" + time
                        , String.class
                ));
    }
}

这里仅仅使用了 spring-cloud-circuitbreaker 的抽象,即 Resilience4JCircuitBreakerFactory 实例,但实际上还是没有 resilience4j-spring 好用的,因此引入 spring-cloud-starter-circuitbreaker-resilience4j 依赖,同时以注解、配置文件的方式使用 resilience4j 这种 “挂羊头卖狗肉” 的行为,我认为也是可以接受的

总结

本章节主要阐述 resilience4jSpring 环境下的使用,同时说明 SpringCloud 下的 resilience4j 整合本质是借助 resilience4j 去实现 SpringCloud熔断 组件能力而非是对 resilience4j 的整合,因此在选择依赖的时候要有清晰的认识~

上一篇:【Spring Cloud】解读 CircuitBreaker 组件 resilience4j 一

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值