Search code examples
javajava-11java-http-client

Java 11 HttpClient - What is Optimum Ratio of HttpClients to Concurrent HttpRequests


In the example below I create one Java 11 httpClient and then create multiple concurrent HttpRequests.

  1. Is this bad practice?
  2. Should each HttpRequest have its own HttpClient?
  3. Is there an upper limit on the number of HttpRequests a HttpClient can have?

Code

    private static void httpClientExample(){
    
    HttpClient httpClient = HttpClient.newHttpClient();

    System.out.println("TP1");

    var task1 = httpClient.sendAsync(HttpRequest.newBuilder()
            .uri(URI.create("https://www.bing.com/"))
            .build(), HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::uri).thenAccept(System.out::println);

    var task2 = httpClient.sendAsync(HttpRequest.newBuilder()
            .uri(URI.create("https://openjdk.java.net/"))
            .build(), HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::uri).thenAccept(System.out::println);
    
    var task3 = httpClient.sendAsync(HttpRequest.newBuilder()
            .uri(URI.create("https://www.google.co.uk/"))
            .build(), HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::uri).thenAccept(System.out::println);


    System.out.println("Requests Sent");

    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println("Main Thread Completed");
    }

Solution

  • This is not explicitly documented in the API docs of HttpClient. But it would be expected that an HttpClient is designed to handle multiple requests. This is in a sense implied on Introduction to the Java HTTP Client:

    Once built, an HttpClient can be used to send multiple requests.

    Now, your question is likely about managing concurrency on your clients. Rather than with using the same instance of HttpClient, this has much to do with the executor service it uses, which is something you can customize (see here):

    ExecutorService executorService = Executors.newFixedThreadPool(10);
    HttpClient httpClient  = HttpClient.newBuilder()
                                   .executor(executorService)
                                   ... //more config
                                   .build();
    

    This way, you can manage the thread pool used by the client to run asynchronous requests.

    In other words:

    Is this bad practice?

    No

    Should each HttpRequest have its own HttpClient?

    No

    Is there an upper limit on the number of HttpRequests a HttpClient can have?

    You will have to test the optimal concurrency settings for your application and then use an executor service configured accordingly.