【问题标题】:Integrating circuitbreaker, retry and timelimiter in Resilience4j在 Resilience4j 中集成断路器、重试和时间限制器
【发布时间】:2020-05-29 15:58:40
【问题描述】:

我正在尝试使用 Resilience4j 功能。

我的用例是结合 3 个模块:

  • 断路器
  • 重试
  • 限时器

我想组合所有这些模块并只执行一次方法

代码

这是我尝试过的。

Supplier<R> supplier = this::doSomething;

timeLimiter.executeFutureSupplier(() -> CompletableFuture.supplyAsync(supplier));

return Decorators.ofSupplier(supplier)
                .withCircuitBreaker(circuitBreaker)
                .withRetry(retry)
                .withBulkhead(bulkhead)
                .decorate();

问题

我的 doSomething() 方法执行两次而不是预期的一次。

之前有人见过这个问题吗?

【问题讨论】:

    标签: execution circuit-breaker resilience4j time-limiting resilience4j-retry


    【解决方案1】:

    您正在使用 timeLimiter.executeFutureSupplier 执行 Future 而不是装饰它。

    请按以下顺序使用:

    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3);
    Supplier<R> supplier = this::doSomething;
    
    CompletableFuture<R> future = Decorators.ofSupplier(supplier)
        .withThreadPoolBulkhead(threadPoolBulkhead)
        .withTimeLimiter(timeLimiter, scheduledExecutorService)
        .withCircuitBreaker(circuitBreaker)
        .withRetry(retry)
        .get().toCompletableFuture();
    

    【讨论】:

    • 如果将速率限制器添加到装饰器中的顺序是什么,即在上面的示例中 withRateLimiter(rateLimiter) 会去哪里?
    • 经过深思熟虑,速率限制器应该介于隔板和时间限制器之间。
    【解决方案2】:

    作为 Resilience4J 创建者 Robert Winkler answered,使用装饰器将 3 个弹性模式组合/应用到供应商。根据执行和弹性的需要调整它们的顺序。

    装饰器的顺序对执行有影响

    Decoratorsbuilder的JavaDoc解释了build-chain order的作用:

    装饰器按构建器链的顺序应用。

    例如,考虑:

    Supplier<String> supplier = Decorators
         .ofSupplier(() -> service.method())  // 1. called and result handled in order:
         .withCircuitBreaker(CircuitBreaker.ofDefaults("id"))  // 2. circuit-breaker
         .withRetry(Retry.ofDefaults("id"))  // 3. retry
         .withFallback(CallNotPermittedException.class, 
              e -> service.fallbackMethod())  // 4. fallback
         .decorate();
    

    (我加了cmets来强调执行顺序)

    这会在执行供应商时产生以下组合: Fallback(Retry(CircuitBreaker(Supplier)))

    这意味着首先调用 Supplier,然后其结果由 CircuitBreaker 处理,然后是 Retry,然后是 Fallback。

    集成客户端RateLimiter

    在 Reflectoring 的教程中推荐 Implementing Rate Limiting with Resilience4j - Reflectoring:

    同时使用 RateLimiter 和重试

    [..] 我们将像往常一样创建RateLimiterRetry 对象。然后我们装饰一个rate-limited SupplierRetry 包装它:[示例]

    订购建议

    将此“Retry with RateLimiter”与上述 JavaDoc 示例和 Robert 的回答进行比较,我建议选择以下执行顺序:

    1. 供应商,然后按顺序装饰有弹性:
    2. RateLimiter(如果超出速率限制,则阻止调用)
    3. TimeLimiter(通话超时)
    4. CircuitBreaker(快速失败)
    5. Retry(异常重试)
    6. Fallback(作为最后手段的后备)

    例如,在 Spring-Boot 扩展中自动配置了合适的参考顺序。参见官方指南,resilience4j-spring-boot2 入门关于Aspect order

    Resilience4j 方面的顺序如下:

    Retry ( CircuitBreaker ( RateLimiter ( TimeLimiter ( Bulkhead ( Function ) ) ) ) )

    所以最后应用重试(如果需要)。

    另见:

    【讨论】:

      猜你喜欢
      • 2022-12-14
      • 2023-03-09
      • 2022-01-06
      • 2020-11-02
      • 2022-08-14
      • 2021-05-09
      • 2021-09-20
      • 2021-06-02
      • 2021-01-19
      相关资源
      最近更新 更多