簡體   English   中英

使用 Java 11 HttpClient 同步與異步的外部服務調用

[英]External service call with Java 11 HttpClient sync vs async

我的微服務正在調用外部服務 POST 調用,我想使用 Java 11 Httpclient。 這里 send() 和 sendAsync() 方法應該如何發揮作用? 我已經測試了多個請求,幾乎相同的延遲。 我嘗試使用 10 或 20 個或更多線程為我的服務執行 100 個端點調用。 兩種方法的結果幾乎相同。

我使用 sendAsync() 和 thenApply().get 來響應接收。 我想知道什么是首選方式,為什么? 使用異步也很快(這不是我目前的結果)?

提前感謝您的回答!

這是兩種方法的測試:

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.Builder;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class HttpClientTest {
    static final int REQUEST_COUNT = 100;
    static final String URI_TEMPLATE = "https://jsonplaceholder.typicode.com/posts/%d";

    public static void main(final String[] args) throws Exception {
        final List<HttpRequest> requests = IntStream.rangeClosed(1, REQUEST_COUNT)
                .mapToObj(i -> String.format(URI_TEMPLATE, i))
                .map(URI::create)
                .map(HttpRequest::newBuilder)
                .map(Builder::build)
                .collect(Collectors.toList());
        final HttpClient client = HttpClient.newBuilder()
                .executor(Executors.newFixedThreadPool(REQUEST_COUNT))
                .build();
        final ThrowingFunction<HttpRequest, String> sendSync =
            request -> client.send(request, BodyHandlers.ofString()).body();
        final ThrowingFunction<CompletableFuture<HttpResponse<String>>, String> getSync =
            future -> future.get().body();
        benchmark("sync", () -> requests.stream()
                .map(sendSync)
                .collect(Collectors.toList()));
        benchmark("async", () -> requests.stream()
                .map(request -> client.sendAsync(request, BodyHandlers.ofString()))
                .collect(Collectors.toList()) // materialize to send the requests
                .stream()
                .map(getSync)
                .collect(Collectors.toList()));
    }

    static void benchmark(final String name, final Supplier<List<String>> supplier) {
        new Thread(() -> {
            final long start = System.nanoTime();
            System.out.printf("%s: start%n", name);
            final List<String> result = supplier.get();
            final Duration duration = Duration.ofNanos(System.nanoTime() - start);
            final int size = result.stream()
                    .mapToInt(String::length)
                    .sum();
            System.out.printf("%s: end, got %d chars, took %s%n", name, size, duration);
        }, name).start();
    }

    @FunctionalInterface
    static interface ThrowingFunction<T, R> extends Function<T, R> {
        default R apply(final T t) {
            try {
                return applyThrowing(t);
            } catch (final Exception e) {
                throw new RuntimeException(e);
            }
        }

        R applyThrowing(T t) throws Exception;
    }
}

示例輸出:

sync: start
async: start
async: end, got 26118 chars, took PT1.6102532S
sync: end, got 26118 chars, took PT4.3368509S

API 的並行級別越高,異步方法的性能就越好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM