1

我正在尝试使用Resilience4j功能。

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

  • 断路器
  • 重试
  • 限时器

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

代码

这是我尝试过的。

Supplier<R> supplier = this::doSomething;

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

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

问题

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

有没有人之前看到过这个问题?

4

2 回答 2

4

您正在使用timeLimiter.executeFutureSupplierwhich 执行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();
于 2020-02-14T06:53:09.247 回答
0

正如 Resilience4J 的创建者Robert Winkler回答的那样,使用装饰器在供应商上组合/应用 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();

(我添加了注释以强调执行顺序)

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

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

集成客户端RateLimiter

正如 Reflectoring 的教程Implementing Rate Limiting with Resilience4j - Reflectoring中所推荐的:

一起使用 RateLimiter 和重试

[..] 我们会像往常一样创建对象RateLimiterRetry然后我们装饰一个速率限制 Supplier并用: [example]包装它Retry

订购建议

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

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

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

Resilience4j Aspects 顺序如下:

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

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

也可以看看:

于 2022-01-08T14:24:07.447 回答