Configure the Netty-based HTTP client
The default HTTP client for asynchronous operations in the AWS SDK for Java 2.x is the Netty-based
NettyNioAsyncHttpClient
As an alternative HTTP client, you can use the new AWS CRT-based HTTP client. This topic shows you how to configure the
NettyNioAsyncHttpClient.
Access the NettyNioAsyncHttpClient
In most situations, you use the NettyNioAsyncHttpClient without any explicit
configuration in asynchronous programs. You declare your asynchronous service clients and
the SDK will configure the NettyNioAsyncHttpClient with standard values for
you.
If you want to explicitly configure the NettyNioAsyncHttpClient or use it with multiple service clients,
you need to make it available for configuration.
No configuration needed
When you declare a dependency on a service client in Maven, the SDK adds a
runtime dependency on the netty-nio-client
artifact. This makes the NettyNioAsyncHttpClient class available to your code at runtime, but not at
compile time. If you are not configuring the Netty-based HTTP client, you don't need
to specify a dependency for it.
In the following XML snippet of a Maven pom.xml file, the dependency
declared with <artifactId>dynamodb-enhanced</artifactId>
transitively brings in the Netty-based HTTP client. You don't need to declare a
dependency specifically for it.
<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.27.21</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>dynamodb-enhanced</artifactId> </dependency> </dependencies>
With these dependencies, you cannot make any HTTP configuration changes, since the
NettyNioAsyncHttpClient library is only on the runtime classpath.
Configuration needed
To configure the NettyNioAsyncHttpClient, you need to add a dependency
on the netty-nio-client artifact at compile time.
Refer to the following example of a Maven pom.xml file to configure the
NettyNioAsyncHttpClient.
<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.27.21</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>dynamodb-enhanced</artifactId> </dependency> <!-- By adding the netty-nio-client dependency, NettyNioAsyncHttpClient will be added to the compile classpath so you can configure it. --> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>netty-nio-client</artifactId> </dependency> </dependencies>
Use and configure the NettyNioAsyncHttpClient
You can configure an instance of NettyNioAsyncHttpClient along with building a service client, or you can
configure a single instance to share across multiple service clients.
With either approach, you use the NettyNioAsyncHttpClient.Builder
Best practice: dedicate a NettyNioAsyncHttpClient instance to a service
client
If you need to configure an instance of the NettyNioAsyncHttpClient, we recommend that you build a
dedicated NettyNioAsyncHttpClient instance. You can do so by using the httpClientBuilder
method of the service client's builder. This way, the lifecycle of the HTTP client
is managed by the SDK, which helps avoid potential memory leaks if the NettyNioAsyncHttpClient instance
is not closed down when it's no longer needed.
The following example creates a DynamoDbAsyncClient instance that is
used by a DynamoDbEnhancedAsyncClient instance. The
DynamoDbAsyncClient instance contains the NettyNioAsyncHttpClient instance with
connectionTimeout and maxConcurrency values. The HTTP
instance is created using httpClientBuilder method of
DynamoDbAsyncClient.Builder.
Imports
import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; import software.amazon.awssdk.awscore.defaultsmode.DefaultsMode; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; import java.time.Duration;
Code
// DynamoDbAsyncClient is the lower-level client used by the enhanced client. DynamoDbAsyncClient dynamoDbAsyncClient = DynamoDbAsyncClient .builder() .httpClientBuilder(NettyNioAsyncHttpClient.builder() .connectionTimeout(Duration.ofMillis(5_000)) .maxConcurrency(100) .tlsNegotiationTimeout(Duration.ofMillis(3_500))) .defaultsMode(DefaultsMode.IN_REGION) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build(); // Singleton: Use dynamoDbAsyncClient and enhancedClient for all requests. DynamoDbEnhancedAsyncClient enhancedClient = DynamoDbEnhancedAsyncClient .builder() .dynamoDbClient(dynamoDbAsyncClient) .extensions(AutoGeneratedTimestampRecordExtension.create()) .build(); // Perform work with the dynamoDbAsyncClient and enhancedClient. // Requests completed: Close dynamoDbAsyncClient. dynamoDbAsyncClient.close();
Alternative approach: share a NettyNioAsyncHttpClient
instance
To help keep resource and memory usage lower for your application, you can configure
a NettyNioAsyncHttpClient and share it across multiple service clients. The HTTP connection pool will
be shared, which lowers resource usage.
Note
When a NettyNioAsyncHttpClient instance is shared, you must close it when it is ready to be disposed.
The SDK will not close the instance when the service client is closed.
The following example configures a Netty-based HTTP client that is used by two service clients. The
configured NettyNioAsyncHttpClient instance is passed to the httpClient method of each
builder. When the service clients and the HTTP client are no longer needed, the code
explicitly closes them. The code closes the HTTP client last.
Imports
import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.s3.S3Client;
Code
// Create a NettyNioAsyncHttpClient shared instance. SdkAsyncHttpClient nettyHttpClient = NettyNioAsyncHttpClient.builder().maxConcurrency(100).build(); // Singletons: Use the s3AsyncClient, dbAsyncClient, and enhancedAsyncClient for all requests. S3AsyncClient s3AsyncClient = S3AsyncClient.builder() .httpClient(nettyHttpClient) .build(); DynamoDbAsyncClient dbAsyncClient = DynamoDbAsyncClient.builder() .httpClient(nettyHttpClient) .defaultsMode(DefaultsMode.IN_REGION) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build(); DynamoDbEnhancedAsyncClient enhancedAsyncClient = DynamoDbEnhancedAsyncClient.builder() .dynamoDbClient(dbAsyncClient) .extensions(AutoGeneratedTimestampRecordExtension.create()) .build(); // Perform work with s3AsyncClient, dbAsyncClient, and enhancedAsyncClient. // Requests completed: Close all service clients. s3AsyncClient.close(); dbAsyncClient.close() nettyHttpClient.close(); // Explicitly close nettyHttpClient.
Configure ALPN protocol negotiation
ALPN (Application-Layer Protocol Negotiation) is a TLS extension that allows the application layer to negotiate which protocol should be performed over a secure connection in a manner that avoids additional round trips and provides better performance.
To enable the Netty-based HTTP client to use ALPN, call the builder methods as shown in the following snippet:
import software.amazon.awssdk.http.Protocol; import software.amazon.awssdk.http.ProtocolNegotiation; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; import software.amazon.awssdk.services.transcribestreaming.TranscribeStreamingAsyncClient; // Configure the Netty-based HTTP client to use the ALPN protocol. SdkAsyncHttpClient nettyClient = NettyNioAsyncHttpClient.builder() .protocol(Protocol.HTTP2) .protocolNegotiation(ProtocolNegotiation.ALPN) .build(); // Use the Netty-based HTTP client with a service client. TranscribeStreamingAsyncClient transcribeClient = TranscribeStreamingAsyncClient.builder() .httpClient(nettyClient) .build();
ALPN protocol negotiation currently works with only with the HTTP/2 protocol as shown in the previous snippet.
Proxy configuration example
The following code snippet uses the proxy configuration builder for the Netty HTTP client
SdkAsyncHttpClient nettyHttpClient = NettyNioAsyncHttpClient.builder() .proxyConfiguration(ProxyConfiguration.builder() .scheme("https") .host("myproxy") .port(1234) .username("username") .password("password") .nonProxyHosts(Set.of("localhost", "host.example.com")) .build()) .build();
The equivalent Java system properties for the proxy configuration are shown in the following command line snippet.
$ java -Dhttps.proxyHost=myproxy -Dhttps.proxyPort=1234 -Dhttps.proxyUser=username \ -Dhttps.proxyPassword=password -Dhttp.nonProxyHosts=localhost|host.example.com -cp ... App
Important
To use any of the HTTPS proxy system properties, the scheme property
must be set in code to https. If the scheme property is not set in
code, the scheme defaults to HTTP and the SDK looks only for http.*
system properties.
The equivalent setup that uses environment variables is:
// Set the following environment variables. // $ export HTTPS_PROXY="https://username:password@myproxy:1234" // $ export NO_PROXY="localhost|host.example.com" // Set the 'useSystemPropertyValues' to false on the proxy configuration. SdkAsyncHttpClient nettyHttpClient = NettyNioAsyncHttpClient.builder() .proxyConfiguration(ProxyConfiguration.builder() .useSystemPropertyValues(Boolean.FALSE) .build()) .build(); // Run the application. // $ java -cp ... App