如何反复调用不可靠的API?与编写在线程中运行的标准try catch块相比,Completable Future会有所帮助吗?

问题描述 投票:0回答:1

我必须每天多次通过网络调用关键API(这使它不可靠)。如果API无法响应(超时)或返回错误(因为服务器依次调用其他不可靠的第三方),则我必须通知他们有关错误,然后再次调用原始API。

这里,错误通知也可能会失败,因此我必须重试通知错误,直到我成功。之后,我可以再次调用原始API。

我想使用CompletableFuture进行构图。对于这种代码,库是正确的选择吗?还是我应该将try catch循环放在一个包装在Runnable中的无限循环中并执行它? CompletableFuture是否会过大?还有其他选择吗?

multithreading asynchronous architecture runnable completable-future
1个回答
0
投票

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

例如:

但是,如果在考虑了替代方法后决定使用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;
}
© www.soinside.com 2019 - 2024. All rights reserved.