如何重复调用不可靠的 API? Completable Future 会比在线程中编写标准的 try catch 块 运行 有用吗?

How to call an unreliable API repeatedly? Will Completable Future be helpful than writing standard try catch block running in a thread?

我必须一次通过网络多次呼叫关键 API(这使得它不可靠),一天多次。如果 API 无法响应(超时)或 returns 错误(因为该服务器反过来调用其他不可靠的第三方)我必须通知他们有关错误,然后调用原始 API 再次.

在这里,错误通知也可能会失败,我将不得不重试通知错误,直到我成功。之后我可以再次调用原始 API。

我想使用 CompletableFuture 构建它。对于这种代码,它是一个正确的库选择吗?或者我应该把一个 try catch 循环放在一个包含在 Runnable 中的无限循环中并执行它? CompletableFuture 会矫枉过正吗?还有其他选择吗?

坦率地说,这个问题太宽泛了,因为答案实际上取决于您已经在使用什么框架。 问题是 - 当今有许多流行的框架提供开箱即用的重试逻辑实现。

例如:

但是,如果在考虑替代方案后您决定使用 CompletableFuture 手动重试,您绝对可以这样做。

例如,以下是重试的简单实用程序:

  • 不限次数:
public static <T> CompletableFuture<T> retry(Throwable throwable, Function<Throwable, T> operation) {
    return CompletableFuture.supplyAsync(() -> operation.apply(throwable))
            .thenApply(CompletableFuture::completedFuture)
            .exceptionally(error -> retry(error, operation))
            .thenCompose(Function.identity());
}

注意:这里我假设,你可以根据Throwable的实例做出一些决定。因此,operation 将错误作为输入并产生一些有用的结果作为输出。在您的情况下,错误 - 可能是 critical API 调用错误,或 notification error,有用的结果 - 成功 critical API 结果。

  • 固定次数(本例为MAX_RETRIES):
public static <T> CompletableFuture<T> retry(Throwable throwable, Function<Throwable, T> operation, int retry) {
    if (retry == MAX_RETRIES) return failedFuture(throwable);

    return CompletableFuture.supplyAsync(() -> operation.apply(throwable))
            .thenApply(CompletableFuture::completedFuture)
            .exceptionally(error -> retry(error, operation, retry + 1))
            .thenCompose(Function.identity());
}

public static <T> CompletableFuture<T> failedFuture(Throwable throwable) {
    final CompletableFuture<T> failedFuture = new CompletableFuture<>();
    failedFuture.completeExceptionally(throwable);
    return failedFuture;
}