multithreadingkotlincompletable-futureasynchttpclient

AsyncHttpClient creates how much threads?


I use async http client in my code to asynchronously handle GET responses I can run simultaneously 100 requests in the same time.

I use just on instance of httpClient in container

@Bean(destroyMethod = "close")
open fun httpClient() = Dsl.asyncHttpClient()

Code looks like

fun method(): CompletableFuture<String> {
    return httpClient.prepareGet("someUrl").execute()
        .toCompletableFuture()
        .thenApply(::getResponseBody)
}

It works fine functionally. In my testing I use mock endpoint with the same url address. But my expectation was that all the requests are handled in several threads, but in profiler I can see that 16 threads are created for AsyncHttpClient, and they aren't destroyed, even if there are no requests to send.

profiler screenshoot

My expectation was that

Am I missing something in my expectations?

UPDATE 1 I saw instruction on https://github.com/AsyncHttpClient/async-http-client/wiki/Connection-pooling I found no info on thread pool

UPDATE 2 I also created method to do the same, but with handler and additional executor pool

Utility method look like

fun <Value, Result> CompletableFuture<Value>.handleResultAsync(executor: Executor, initResultHandler: ResultHandler<Value, Result>.() -> Unit): CompletableFuture<Result> {
    val rh = ResultHandler<Value, Result>()
    rh.initResultHandler()

    val handler = BiFunction { value: Value?, exception: Throwable? ->
        if (exception == null) rh.success?.invoke(value) else rh.fail?.invoke(exception)
    }

    return handleAsync(handler, executor)
}

The updated method look like

fun method(): CompletableFuture<String> {
    return httpClient.prepareGet("someUrl").execute()
        .toCompletableFuture()
        .handleResultAsync(executor) {
            success = {response ->
                logger.info("ok")
                getResponseBody(response!!)
            }
            fail = { ex ->
                logger.error("Failed to execute request", ex)
                throw ex
            }
    }
}

Then I can see that result of GET method is executed in the threads provided by thread pool (previously result was executed in "AsyncHttpClient-3-x"), but additional thread for AsyncHttpClient are still created and not destroyed.


Solution

  • AHC has two types of threads:

    1. For I/O operation. On your screen, it's AsyncHttpClient-x-x threads. AHC creates 2*core_number of those.
    2. For timeouts. On your screen, it's AsyncHttpClient-timer-1-1 thread. Should be only one.

    Source: issue on GitHub: https://github.com/AsyncHttpClient/async-http-client/issues/1658