1*8a52c783SCole Faust## AWS Java SDK 2.x Best Practices 2*8a52c783SCole Faust 3*8a52c783SCole FaustHere are the best practices of using AWS Java SDK 2.x. 4*8a52c783SCole Faust 5*8a52c783SCole Faust### Reuse SDK client if possible 6*8a52c783SCole Faust 7*8a52c783SCole FaustEach SDK client maintains its own HTTP connection pool so that connections can be reused by a new request 8*8a52c783SCole Faustto cut down the time to establish a new connection. It is recommended to share a single instance of the client to 9*8a52c783SCole Faustavoid the overhead of having too many connection pools that are not being utilized effectively. All SDK clients are thread safe. 10*8a52c783SCole Faust 11*8a52c783SCole FaustIf it is not desirable to share a client instance, invoke `client.close()` to release the resources once the client is not needed. 12*8a52c783SCole Faust 13*8a52c783SCole Faust### Close input streams from client operations 14*8a52c783SCole Faust 15*8a52c783SCole FaustFor streaming operations such as `S3Client#getObject`, if you are working with `ResponseInputStream` directly, we have the following recommendations: 16*8a52c783SCole Faust 17*8a52c783SCole Faust- Read all the data from the input stream as soon as possible 18*8a52c783SCole Faust- Close the input stream as soon as possible 19*8a52c783SCole Faust 20*8a52c783SCole FaustThis is because the input stream is a direct stream of data from the HTTP connection and the underlying HTTP connection cannot be 21*8a52c783SCole Faustreused until all data from the stream has been read and the stream is closed. If these rules are not followed, the client can 22*8a52c783SCole Faustrun out of resources by allocating too many open, but unused, HTTP connections. 23*8a52c783SCole Faust 24*8a52c783SCole Faust### Close input streams of responseBody() from Custom Client based on SdkHttpClient 25*8a52c783SCole FaustWhile implementing custom clients from `SdkHttpClient` interface 26*8a52c783SCole Faust- Close the [responseBody](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/HttpExecuteResponse.html#responseBody()) Input Stream: Always close the "responseBody" input stream to release the HTTP Connection, even when handling error responses. 27*8a52c783SCole Faust- SDK Requirement: The SDK requires the closing of the input stream to manage HTTP connections effectively. 28*8a52c783SCole Faust- Handling Error Responses: Even in the case of error responses, the SDK client creates an input stream for reading error data. 29*8a52c783SCole Faust- Consistent Practice: Ensure that consumers close the input stream in the "responseBody" attribute for both success and error cases. 30*8a52c783SCole Faust 31*8a52c783SCole Faust### Tune HTTP configurations based on performance tests 32*8a52c783SCole Faust 33*8a52c783SCole FaustThe SDK provides a set of [default http configurations] that apply to general use cases. Customers are recommended to tune the configurations for their applications based on their use cases. 34*8a52c783SCole Faust 35*8a52c783SCole Faust### Use OpenSSL for Netty async client 36*8a52c783SCole Faust 37*8a52c783SCole FaustBy default, `NettyNioAsyncHttpClient` uses JDK as the SslProvider. In our local tests, we found that using `OpenSSL` 38*8a52c783SCole Faustis more performant than JDK. Using OpenSSL is also the recommended approach by Netty community, see [Netty TLS with OpenSSL]. 39*8a52c783SCole FaustNote that you need to add `netty-tcnative` to your dependency in order to use OpenSSL, see [Configuring netty-tcnative] 40*8a52c783SCole Faust 41*8a52c783SCole FaustOnce you have `netty-tcnative` configured correctly, `NettyAsyncHttpClient` will select OpenSSL automatically, or you can set the 42*8a52c783SCole Faust`SslProvider` explicitly on the NettyNioAsyncHttpClient builder. 43*8a52c783SCole Faust 44*8a52c783SCole Faust``` 45*8a52c783SCole Faust NettyNioAsyncHttpClient.builder() 46*8a52c783SCole Faust .sslProvider(SslProvider.OPENSSL) 47*8a52c783SCole Faust .build(); 48*8a52c783SCole Faust``` 49*8a52c783SCole Faust 50*8a52c783SCole Faust### Utilize timeout configurations 51*8a52c783SCole Faust 52*8a52c783SCole FaustThe SDK provides timeout configurations on requests out of box and they can be configured via `ClientOverrideConfiguration#apiCallAttemptTimeout` and `ClientOverrideConfiguration#ApiCallTimeout`. 53*8a52c783SCole Faust 54*8a52c783SCole Faust```java 55*8a52c783SCole Faust S3Client.builder() 56*8a52c783SCole Faust .overrideConfiguration(b -> b.apiCallTimeout(Duration.ofMillis(API_CALL_TIMEOUT)) 57*8a52c783SCole Faust .apiCallAttemptTimeout(Duration.ofMillis(API_CALL_ATTEMPT_TIMEOUT)) 58*8a52c783SCole Faust .build(); 59*8a52c783SCole Faust``` 60*8a52c783SCole Faust 61*8a52c783SCole Faust- `ApiCallAttemptTimeout` tracks the amount of time for a single http attempt and the request can be retried if timed out on api call attempt. 62*8a52c783SCole Faust- `ApiCallTimeout` configures the amount of time for the entire execution including all retry attempts. 63*8a52c783SCole Faust 64*8a52c783SCole FaustBy default, timeouts are disabled. Using them together is helpful to set a hard limit on total time spent on all attempts across retries and each individual HTTP request to fail fast on one slow request. 65*8a52c783SCole Faust 66*8a52c783SCole Faust[default http configurations]: https://github.com/aws/aws-sdk-java-v2/blob/master/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpConfigurationOption.java 67*8a52c783SCole Faust[Netty TLS with OpenSSL]: https://netty.io/wiki/requirements-for-4.x.html#tls-with-openssl 68*8a52c783SCole Faust[Configuring netty-tcnative]: https://netty.io/wiki/forked-tomcat-native.html