如何使用 AsyncRestTemplate 同时进行多个调用?

2022-09-02 09:52:45

我不明白如何有效地用于进行外部服务调用。对于下面的代码:AsyncRestTemplate

class Foo {

    public void doStuff() {
        Future<ResponseEntity<String>> future1 = asyncRestTemplate.getForEntity(
                url1, String.class);
        String response1 = future1.get();

        Future<ResponseEntity<String>> future2 = asyncRestTemplate.getForEntity(
                url2, String.class);
        String response2 = future2.get();

        Future<ResponseEntity<String>> future3 = asyncRestTemplate.getForEntity(
                url3, String.class);
        String response3 = future3.get();
    }
}

理想情况下,我希望同时执行所有3个调用,并在全部完成后处理结果。但是,每个外部服务调用在被调用之前不会提取,但会被阻止。那么,这难道不会违背目的吗?我不妨使用.get()get()AsyncRestTemplateRestTemplate

所以我不明白如何让他们同时执行?


答案 1

在调度所有异步调用之前,不要调用阻塞:get()

class Foo {
  public void doStuff() {
    ListenableFuture<ResponseEntity<String>> future1 = asyncRestTemplate
        .getForEntity(url1, String.class);
    ListenableFuture<ResponseEntity<String>> future2 = asyncRestTemplate
        .getForEntity(url2, String.class);
    ListenableFuture<ResponseEntity<String>> future3 = asyncRestTemplate
        .getForEntity(url3, String.class);

    String response1 = future1.get();
    String response2 = future2.get();
    String response3 = future3.get();
  }
}

您可以同时执行调度进入循环,但请注意,当前的结果收集效率低下,因为它会卡在下一个未完成的未来。

您可以将所有期货添加到集合中,并循环访问它,测试每个期货是否为非阻塞。当该调用返回 true 时,可以调用 。isDone()get()

通过这种方式,您的集体结果收集将得到优化,而不是按照调用s的顺序等待下一个缓慢的未来结果。get()

更好的是,您可以在每个返回的 中注册回调(运行时),而不必担心循环检查潜在结果。ListenableFutureAccyncRestTemplate


答案 2

如果你不必使用'AsyncRestTemplate',我建议你改用RxJava。RxJava zip运算符就是您正在寻找的。检查以下代码:

private rx.Observable<String> externalCall(String url, int delayMilliseconds) {
    return rx.Observable.create(
            subscriber -> {
                try {
                    Thread.sleep(delayMilliseconds); //simulate long operation
                    subscriber.onNext("response(" + url + ") ");
                    subscriber.onCompleted();
                } catch (InterruptedException e) {
                    subscriber.onError(e);
                }
            }
    );
}

public void callServices() {
    rx.Observable<String> call1 = externalCall("url1", 1000).subscribeOn(Schedulers.newThread());
    rx.Observable<String> call2 = externalCall("url2", 4000).subscribeOn(Schedulers.newThread());
    rx.Observable<String> call3 = externalCall("url3", 5000).subscribeOn(Schedulers.newThread());
    rx.Observable.zip(call1, call2, call3, (resp1, resp2, resp3) -> resp1 + resp2 + resp3)
            .subscribeOn(Schedulers.newThread())
            .subscribe(response -> System.out.println("done with: " + response));
}

对外部服务的所有请求都将在单独的线程中执行,当最后一次调用完成时,将应用转换函数(例如简单字符串串联),并且结果(串联字符串)将从“zip”可观察中发出。


推荐