-
Notifications
You must be signed in to change notification settings - Fork 957
Description
Describe the issue
This is regarding the usage of NettyNioAsyncHttpClient connection pool with aws 2.17.99 sqs sdk which is being used in our sqs poller application,
on setting maxConcurrency=200(or even 1000) and maxPendingConnectionAcquires = 20000,
Java sqs async sdk client works to fetch data, however while higher aws sqs fetch tps, we encounter the log saying time as "10000 milliseconds." and not 20000 as set by our code as below. Hence we believe that sqs client is using the default connection pool of maxPendingConnectionAcquires = 10000 & maxConcurrency = 50, dishonouring our configured connection pool of maxPendingConnectionAcquires = 20000 & maxConcurrency = 200 (NettyNioAsyncHttpClient).
code usage -:
sqsClient = super.initBuilderConfig(sqsClientBuilder).httpClientBuilder(ApacheHttpClient.builder()
.maxConnections(200).connectionAcquisitionTimeout(Duration.ofMillis(20000)))
.build();
sqsAsyncClient = super.initBuilderConfig(sqsAsyncClientBuilder).httpClientBuilder(NettyNioAsyncHttpClient.builder()
.maxConcurrency(200).maxPendingConnectionAcquires(20000))
.build();
Reference-:
https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/http-configuration-netty.html
we are facing the below stack trace-:
=============================================================================================
java.util.concurrent.CompletionException: software.amazon.awssdk.core.exception.SdkClientException: Unable to execute HTTP request: Acquire operation took longer than the configured maximum time. This indicates that a request cannot get a connection from the pool within the specified maximum time. This can be due to high request rate.
Consider taking any of the following actions to mitigate the issue: increase max connections, increase acquire timeout, or slowing the request rate.
Increasing the max connections can increase client throughput (unless the network interface is already fully utilized), but can eventually start to hit operation system limitations on the number of file descriptors used by the process. If you already are fully utilizing your network interface or cannot further increase your connection count, increasing the acquire timeout gives extra time for requests to acquire a connection before timing out. If the connections doesn't free up, the subsequent requests will still timeout.
If the above mechanisms are not able to fix the issue, try smoothing out your requests so that large traffic bursts cannot overload the client, being more efficient with the number of times you need to call AWS, or by increasing the number of hosts sending requests.
at software.amazon.awssdk.utils.CompletableFutureUtils.errorAsCompletionException(CompletableFutureUtils.java:62) ~[utils-2.17.99.jar!/:na]
at software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncExecutionFailureExceptionReportingStage.lambda$execute$0(AsyncExecutionFailureExceptionReportingStage.java:51) ~[sdk-core-2.17.99.jar!/:na]
at java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:836) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:811) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990) ~[na:1.8.0_312-debug]
at software.amazon.awssdk.utils.CompletableFutureUtils.lambda$forwardExceptionTo$0(CompletableFutureUtils.java:76) ~[utils-2.17.99.jar!/:na]
at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990) ~[na:1.8.0_312-debug]
at software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncRetryableStage$RetryingExecutor.maybeAttemptExecute(AsyncRetryableStage.java:103) ~[sdk-core-2.17.99.jar!/:na]
at software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncRetryableStage$RetryingExecutor.maybeRetryExecute(AsyncRetryableStage.java:181) ~[sdk-core-2.17.99.jar!/:na]
at software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncRetryableStage$RetryingExecutor.lambda$attemptExecute$1(AsyncRetryableStage.java:159) ~[sdk-core-2.17.99.jar!/:na]
at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990) ~[na:1.8.0_312-debug]
at software.amazon.awssdk.utils.CompletableFutureUtils.lambda$forwardExceptionTo$0(CompletableFutureUtils.java:76) ~[utils-2.17.99.jar!/:na]
at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990) ~[na:1.8.0_312-debug]
at software.amazon.awssdk.core.internal.http.pipeline.stages.MakeAsyncHttpRequestStage.lambda$null$0(MakeAsyncHttpRequestStage.java:104) ~[sdk-core-2.17.99.jar!/:na]
at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:774) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:750) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488) ~[na:1.8.0_312-debug]
at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990) ~[na:1.8.0_312-debug]
at software.amazon.awssdk.core.internal.http.pipeline.stages.MakeAsyncHttpRequestStage$WrappedErrorForwardingResponseHandler.onError(MakeAsyncHttpRequestStage.java:158) ~[sdk-core-2.17.99.jar!/:na]
at software.amazon.awssdk.http.nio.netty.internal.NettyRequestExecutor.handleFailure(NettyRequestExecutor.java:302) ~[netty-nio-client-2.17.99.jar!/:na]
at software.amazon.awssdk.http.nio.netty.internal.NettyRequestExecutor.makeRequestListener(NettyRequestExecutor.java:174) ~[netty-nio-client-2.17.99.jar!/:na]
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:578) ~[netty-common-4.1.68.Final.jar!/:4.1.68.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:552) ~[netty-common-4.1.68.Final.jar!/:4.1.68.Final]
at io.netty.util.concurrent.DefaultPromise.access$200(DefaultPromise.java:35) ~[netty-common-4.1.68.Final.jar!/:4.1.68.Final]
at io.netty.util.concurrent.DefaultPromise$1.run(DefaultPromise.java:502) ~[netty-common-4.1.68.Final.jar!/:4.1.68.Final]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164) ~[netty-common-4.1.68.Final.jar!/:4.1.68.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469) ~[netty-common-4.1.68.Final.jar!/:4.1.68.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497) ~[netty-transport-4.1.68.Final.jar!/:4.1.68.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.68.Final.jar!/:4.1.68.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.68.Final.jar!/:4.1.68.Final]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_312-debug]
Caused by: software.amazon.awssdk.core.exception.SdkClientException: Unable to execute HTTP request: Acquire operation took longer than the configured maximum time. This indicates that a request cannot get a connection from the pool within the specified maximum time. This can be due to high request rate.
Consider taking any of the following actions to mitigate the issue: increase max connections, increase acquire timeout, or slowing the request rate.
Increasing the max connections can increase client throughput (unless the network interface is already fully utilized), but can eventually start to hit operation system limitations on the number of file descriptors used by the process. If you already are fully utilizing your network interface or cannot further increase your connection count, increasing the acquire timeout gives extra time for requests to acquire a connection before timing out. If the connections doesn't free up, the subsequent requests will still timeout.
If the above mechanisms are not able to fix the issue, try smoothing out your requests so that large traffic bursts cannot overload the client, being more efficient with the number of times you need to call AWS, or by increasing the number of hosts sending requests.
at software.amazon.awssdk.core.exception.SdkClientException$BuilderImpl.build(SdkClientException.java:98) ~[sdk-core-2.17.99.jar!/:na]
at software.amazon.awssdk.core.exception.SdkClientException.create(SdkClientException.java:43) ~[sdk-core-2.17.99.jar!/:na]
at software.amazon.awssdk.core.internal.http.pipeline.stages.utils.RetryableStageHelper.setLastException(RetryableStageHelper.java:204) ~[sdk-core-2.17.99.jar!/:na]
at software.amazon.awssdk.core.internal.http.pipeline.stages.utils.RetryableStageHelper.setLastException(RetryableStageHelper.java:200) ~[sdk-core-2.17.99.jar!/:na]
at software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncRetryableStage$RetryingExecutor.maybeRetryExecute(AsyncRetryableStage.java:179) ~[sdk-core-2.17.99.jar!/:na]
... 28 common frames omitted
Caused by: java.lang.Throwable: Acquire operation took longer than the configured maximum time. This indicates that a request cannot get a connection from the pool within the specified maximum time. This can be due to high request rate.
Consider taking any of the following actions to mitigate the issue: increase max connections, increase acquire timeout, or slowing the request rate.
Increasing the max connections can increase client throughput (unless the network interface is already fully utilized), but can eventually start to hit operation system limitations on the number of file descriptors used by the process. If you already are fully utilizing your network interface or cannot further increase your connection count, increasing the acquire timeout gives extra time for requests to acquire a connection before timing out. If the connections doesn't free up, the subsequent requests will still timeout.
If the above mechanisms are not able to fix the issue, try smoothing out your requests so that large traffic bursts cannot overload the client, being more efficient with the number of times you need to call AWS, or by increasing the number of hosts sending requests.
at software.amazon.awssdk.http.nio.netty.internal.NettyRequestExecutor.decorateException(NettyRequestExecutor.java:308) ~[netty-nio-client-2.17.99.jar!/:na]
at software.amazon.awssdk.http.nio.netty.internal.NettyRequestExecutor.handleFailure(NettyRequestExecutor.java:301) ~[netty-nio-client-2.17.99.jar!/:na]
... 11 common frames omitted
Caused by: java.util.concurrent.TimeoutException: Acquire operation took longer than 10000 milliseconds.
at software.amazon.awssdk.http.nio.netty.internal.HealthCheckedChannelPool.timeoutAcquire(HealthCheckedChannelPool.java:77) ~[netty-nio-client-2.17.99.jar!/:na]
at software.amazon.awssdk.http.nio.netty.internal.HealthCheckedChannelPool.lambda$acquire$0(HealthCheckedChannelPool.java:67) ~[netty-nio-client-2.17.99.jar!/:na]
at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98) ~[netty-common-4.1.68.Final.jar!/:4.1.68.Final]
at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170) ~[netty-common-4.1.68.Final.jar!/:4.1.68.Final]
... 6 common frames omitted
=============================================================================================
Java sqs async sdk client works to fetch data, however while higher aws sqs fetch tps, we encounter the log saying time as "10000 milliseconds." and not 20000 as set by our code as below
code usage -:
sqsClient = super.initBuilderConfig(sqsClientBuilder).httpClientBuilder(ApacheHttpClient.builder()
.maxConnections(200).connectionAcquisitionTimeout(Duration.ofMillis(20000)))
.build();
sqsAsyncClient = super.initBuilderConfig(sqsAsyncClientBuilder).httpClientBuilder(NettyNioAsyncHttpClient.builder()
.maxConcurrency(200).maxPendingConnectionAcquires(20000))
.build();
Reference-:
https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/http-configuration-netty.html
Expected behavior
connection pool of maxPendingConnectionAcquires = 20000 & maxConcurrency = 200 (NettyNioAsyncHttpClient) should be applied
Current behavior
connection pool of maxPendingConnectionAcquires = 20000 & maxConcurrency = 200 (NettyNioAsyncHttpClient) is not being applied and currently using the default of maxPendingConnectionAcquires= 10000, maxConcurrency = 50
Steps to Reproduce
code usage -:
sqsClient = super.initBuilderConfig(sqsClientBuilder).httpClientBuilder(ApacheHttpClient.builder()
.maxConnections(200).connectionAcquisitionTimeout(Duration.ofMillis(20000)))
.build();
sqsAsyncClient = super.initBuilderConfig(sqsAsyncClientBuilder).httpClientBuilder(NettyNioAsyncHttpClient.builder()
.maxConcurrency(200).maxPendingConnectionAcquires(20000))
.build();
protected <E extends AwsClientBuilder> E initBuilderConfig(E builder) {
StsClient stsClient = StsClient.builder().region(Region.of(getConfig().getRegion())).credentialsProvider(StaticCredentialsProvider.create(config.getCredential())).build();
AssumeRoleRequest assumeRoleRequest = AssumeRoleRequest.builder()
.roleArn(config.getRoleArn())
.roleSessionName(config.getRoleSessionName())
.build();
AssumeRoleResponse assumeRoleResponse = stsClient.assumeRole(assumeRoleRequest);
Credentials credentials = assumeRoleResponse.credentials();
AwsSessionCredentials awsSessionCredentials = AwsSessionCredentials.create(credentials.accessKeyId(), credentials.secretAccessKey(), credentials.sessionToken());
builder.region(Region.of(getConfig().getRegion())).credentialsProvider(StaticCredentialsProvider.create(awsSessionCredentials)).build();
return builder;
}
Possible Solution
No response
Context
No response
AWS Java SDK version used
2.17.99
JDK version used
8
Operating System and version
centos rhel fedora (Amazon Linux 2)