Skip to content

Commit f7a9464

Browse files
committed
Updating SDK to work with most recent CRT
Factoring out EventLoopGroup/HostResolver from client constructor, fixing bug reported by Sonar
1 parent bfab2f3 commit f7a9464

File tree

12 files changed

+146
-49
lines changed

12 files changed

+146
-49
lines changed

http-clients/aws-crt-client/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<parent>
2222
<artifactId>http-clients</artifactId>
2323
<groupId>software.amazon.awssdk</groupId>
24-
<version>2.10.9-SNAPSHOT</version>
24+
<version>2.10.55-SNAPSHOT</version>
2525
</parent>
2626
<modelVersion>4.0.0</modelVersion>
2727

@@ -33,7 +33,7 @@
3333
<dependency>
3434
<groupId>software.amazon.awssdk.crt</groupId>
3535
<artifactId>aws-crt</artifactId>
36-
<version>0.4.1</version>
36+
<version>0.4.19</version>
3737
</dependency>
3838

3939
<!--SDK dependencies-->

http-clients/aws-crt-client/src/it/java/software/amazon/awssdk/http/crt/AwsCrtClientCallingPatternIntegrationTest.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.junit.experimental.theories.Theory;
3333
import org.junit.runner.RunWith;
3434
import software.amazon.awssdk.crt.CrtResource;
35+
import software.amazon.awssdk.crt.io.EventLoopGroup;
36+
import software.amazon.awssdk.crt.io.HostResolver;
3537
import software.amazon.awssdk.http.SdkHttpConfigurationOption;
3638
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
3739
import software.amazon.awssdk.regions.Region;
@@ -95,8 +97,12 @@ private boolean testWithClient(KmsAsyncClient asyncKMSClient, int numberOfReques
9597
}
9698

9799
private boolean testWithNewClient(int eventLoopSize, int numberOfRequests) {
98-
try (SdkAsyncHttpClient newAwsCrtHttpClient = AwsCrtAsyncHttpClient.builder()
99-
.eventLoopSize(eventLoopSize)
100+
101+
try (EventLoopGroup eventLoopGroup = new EventLoopGroup(eventLoopSize);
102+
HostResolver hostResolver = new HostResolver(eventLoopGroup);
103+
SdkAsyncHttpClient newAwsCrtHttpClient = AwsCrtAsyncHttpClient.builder()
104+
.eventLoopGroup(eventLoopGroup)
105+
.hostResolver(hostResolver)
100106
.build()) {
101107
try (KmsAsyncClient newAsyncKMSClient = KmsAsyncClient.builder()
102108
.region(REGION)
@@ -156,9 +162,12 @@ public void checkAllCombinations(@FromDataPoints("EventLoop") int eventLoopSize,
156162
.put(SdkHttpConfigurationOption.MAX_CONNECTIONS, connectionPoolSize)
157163
.build();
158164

165+
EventLoopGroup eventLoopGroup = new EventLoopGroup(eventLoopSize);
166+
HostResolver hostResolver = new HostResolver(eventLoopGroup);
159167

160168
SdkAsyncHttpClient awsCrtHttpClient = AwsCrtAsyncHttpClient.builder()
161-
.eventLoopSize(eventLoopSize)
169+
.eventLoopGroup(eventLoopGroup)
170+
.hostResolver(hostResolver)
162171
.buildWithDefaults(attributes);
163172

164173
KmsAsyncClient sharedAsyncKMSClient = KmsAsyncClient.builder()
@@ -194,6 +203,9 @@ public void checkAllCombinations(@FromDataPoints("EventLoop") int eventLoopSize,
194203
awsCrtHttpClient.close();
195204
Assert.assertFalse(failed.get());
196205

206+
hostResolver.close();
207+
eventLoopGroup.close();
208+
197209
CrtResource.waitForNoResources();
198210

199211
float numSeconds = (float) ((System.currentTimeMillis() - start) / 1000.0);

http-clients/aws-crt-client/src/it/java/software/amazon/awssdk/http/crt/AwsCrtClientKmsIntegrationTest.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import org.junit.Test;
1212
import software.amazon.awssdk.core.SdkBytes;
1313
import software.amazon.awssdk.crt.CrtResource;
14+
import software.amazon.awssdk.crt.io.EventLoopGroup;
15+
import software.amazon.awssdk.crt.io.HostResolver;
1416
import software.amazon.awssdk.crt.io.TlsCipherPreference;
1517
import software.amazon.awssdk.crt.io.TlsContextOptions;
1618
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
@@ -32,6 +34,8 @@ public class AwsCrtClientKmsIntegrationTest {
3234
private static String KEY_ALIAS = "alias/aws-sdk-java-v2-integ-test";
3335
private static Region REGION = Region.US_EAST_1;
3436
private static List<SdkAsyncHttpClient> awsCrtHttpClients = new ArrayList<>();
37+
private static EventLoopGroup eventLoopGroup;
38+
private static HostResolver hostResolver;
3539

3640
@Before
3741
public void setup() {
@@ -43,9 +47,13 @@ public void setup() {
4347
continue;
4448
}
4549

50+
int numThreads = 1;
51+
eventLoopGroup = new EventLoopGroup(numThreads);
52+
hostResolver = new HostResolver(eventLoopGroup);
4653

4754
SdkAsyncHttpClient awsCrtHttpClient = AwsCrtAsyncHttpClient.builder()
48-
.eventLoopSize(1)
55+
.eventLoopGroup(eventLoopGroup)
56+
.hostResolver(hostResolver)
4957
.build();
5058

5159
awsCrtHttpClients.add(awsCrtHttpClient);
@@ -55,6 +63,8 @@ public void setup() {
5563

5664
@After
5765
public void tearDown() {
66+
hostResolver.close();
67+
eventLoopGroup.close();
5868
CrtResource.waitForNoResources();
5969
}
6070

http-clients/aws-crt-client/src/it/java/software/amazon/awssdk/http/crt/AwsCrtClientS3IntegrationTest.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import software.amazon.awssdk.core.ResponseBytes;
3131
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
3232
import software.amazon.awssdk.crt.CrtResource;
33+
import software.amazon.awssdk.crt.io.EventLoopGroup;
34+
import software.amazon.awssdk.crt.io.HostResolver;
3335
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
3436
import software.amazon.awssdk.regions.Region;
3537
import software.amazon.awssdk.services.s3.S3AsyncClient;
@@ -50,6 +52,8 @@ public class AwsCrtClientS3IntegrationTest {
5052

5153
private static Region REGION = Region.US_EAST_1;
5254

55+
private static EventLoopGroup eventLoopGroup;
56+
private static HostResolver hostResolver;
5357
private static SdkAsyncHttpClient crtClient;
5458

5559
private static S3AsyncClient s3;
@@ -58,8 +62,13 @@ public class AwsCrtClientS3IntegrationTest {
5862
public void setup() {
5963
CrtResource.waitForNoResources();
6064

65+
int numThreads = 4;
66+
eventLoopGroup = new EventLoopGroup(numThreads);
67+
hostResolver = new HostResolver(eventLoopGroup);
68+
6169
crtClient = AwsCrtAsyncHttpClient.builder()
62-
.eventLoopSize(4)
70+
.eventLoopGroup(eventLoopGroup)
71+
.hostResolver(hostResolver)
6372
.build();
6473

6574
s3 = S3AsyncClient.builder()
@@ -73,7 +82,8 @@ public void setup() {
7382
public void tearDown() {
7483
s3.close();
7584
crtClient.close();
76-
85+
hostResolver.close();
86+
eventLoopGroup.close();
7787
CrtResource.waitForNoResources();
7888
}
7989

@@ -108,4 +118,4 @@ public void testParallelDownloadFromS3() throws Exception {
108118
}
109119
}
110120

111-
}
121+
}

http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.java

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
* Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
@@ -30,9 +30,12 @@
3030
import software.amazon.awssdk.annotations.SdkPublicApi;
3131
import software.amazon.awssdk.crt.CrtResource;
3232
import software.amazon.awssdk.crt.http.HttpClientConnectionManager;
33+
import software.amazon.awssdk.crt.http.HttpClientConnectionManagerOptions;
3334
import software.amazon.awssdk.crt.http.HttpHeader;
3435
import software.amazon.awssdk.crt.http.HttpRequest;
3536
import software.amazon.awssdk.crt.io.ClientBootstrap;
37+
import software.amazon.awssdk.crt.io.EventLoopGroup;
38+
import software.amazon.awssdk.crt.io.HostResolver;
3639
import software.amazon.awssdk.crt.io.SocketOptions;
3740
import software.amazon.awssdk.crt.io.TlsCipherPreference;
3841
import software.amazon.awssdk.crt.io.TlsContext;
@@ -80,9 +83,10 @@ public AwsCrtAsyncHttpClient(DefaultBuilder builder, AttributeMap config) {
8083
int maxConns = config.get(SdkHttpConfigurationOption.MAX_CONNECTIONS);
8184

8285
Validate.isPositive(maxConns, "maxConns");
83-
Validate.isPositive(builder.eventLoopSize, "eventLoopSize");
8486
Validate.notNull(builder.cipherPreference, "cipherPreference");
8587
Validate.isPositive(builder.windowSize, "windowSize");
88+
Validate.notNull(builder.eventLoopGroup, "eventLoopGroup");
89+
Validate.notNull(builder.hostResolver, "hostResolver");
8690

8791
/**
8892
* Must call own() in same order that CrtResources are created in, so that they will be closed in reverse order.
@@ -93,12 +97,16 @@ public AwsCrtAsyncHttpClient(DefaultBuilder builder, AttributeMap config) {
9397
* in the correct order.
9498
*/
9599

96-
bootstrap = own(new ClientBootstrap(builder.eventLoopSize));
97-
socketOptions = own(new SocketOptions());
98-
tlsContextOptions = own(TlsContextOptions.createDefaultClient().withCipherPreference(builder.cipherPreference));
99-
tlsContextOptions.setVerifyPeer(builder.verifyPeer);
100-
tlsContext = own(new TlsContext(tlsContextOptions));
100+
this.bootstrap = own(new ClientBootstrap(builder.eventLoopGroup, builder.hostResolver));
101+
this.socketOptions = own(new SocketOptions());
101102

103+
try (TlsContextOptions defaultClientOptions = TlsContextOptions.createDefaultClient()
104+
.withCipherPreference(builder.cipherPreference)
105+
.withVerifyPeer(builder.verifyPeer)) {
106+
this.tlsContextOptions = own(defaultClientOptions);
107+
}
108+
109+
this.tlsContext = own(new TlsContext(this.tlsContextOptions));
102110
this.windowSize = builder.windowSize;
103111
this.maxConnectionsPerEndpoint = maxConns;
104112
}
@@ -135,8 +143,15 @@ private HttpClientConnectionManager createConnectionPool(URI uri) {
135143
Validate.notNull(uri, "URI must not be null");
136144
log.debug(() -> "Creating ConnectionPool for: URI:" + uri + ", MaxConns: " + maxConnectionsPerEndpoint);
137145

138-
return new HttpClientConnectionManager(bootstrap, socketOptions, tlsContext, uri, windowSize,
139-
maxConnectionsPerEndpoint);
146+
HttpClientConnectionManagerOptions options = new HttpClientConnectionManagerOptions();
147+
options.withClientBootstrap(bootstrap)
148+
.withSocketOptions(socketOptions)
149+
.withTlsContext(tlsContext)
150+
.withUri(uri)
151+
.withWindowSize(windowSize)
152+
.withMaxConnections(maxConnectionsPerEndpoint);
153+
154+
return HttpClientConnectionManager.create(options);
140155
}
141156

142157
private HttpClientConnectionManager getOrCreateConnectionPool(URI uri) {
@@ -194,7 +209,7 @@ private HttpHeader[] asArray(List<HttpHeader> crtHeaderList) {
194209
return crtHeaderList.toArray(new HttpHeader[crtHeaderList.size()]);
195210
}
196211

197-
private HttpRequest toCrtRequest(URI uri, AsyncExecuteRequest asyncRequest) {
212+
private HttpRequest toCrtRequest(URI uri, AsyncExecuteRequest asyncRequest, AwsCrtAsyncHttpStreamAdapter crtToSdkAdapter) {
198213
SdkHttpRequest sdkRequest = asyncRequest.request();
199214
Validate.notNull(uri, "URI must not be null");
200215
Validate.notNull(sdkRequest, "SdkHttpRequest must not be null");
@@ -207,7 +222,7 @@ private HttpRequest toCrtRequest(URI uri, AsyncExecuteRequest asyncRequest) {
207222

208223
HttpHeader[] crtHeaderArray = asArray(createHttpHeaderList(uri, asyncRequest));
209224

210-
return new HttpRequest(method, encodedPath + encodedQueryString, crtHeaderArray);
225+
return new HttpRequest(method, encodedPath + encodedQueryString, crtHeaderArray, crtToSdkAdapter);
211226
}
212227

213228
@Override
@@ -222,13 +237,12 @@ public CompletableFuture<Void> execute(AsyncExecuteRequest asyncRequest) {
222237

223238
URI uri = toUri(asyncRequest.request());
224239
HttpClientConnectionManager crtConnPool = getOrCreateConnectionPool(uri);
225-
HttpRequest crtRequest = toCrtRequest(uri, asyncRequest);
226-
227240
CompletableFuture<Void> requestFuture = new CompletableFuture<>();
228241

229242
// When a Connection is ready from the Connection Pool, schedule the Request on the connection
230243
crtConnPool.acquireConnection()
231244
.whenComplete((crtConn, throwable) -> {
245+
232246
// If we didn't get a connection for some reason, fail the request
233247
if (throwable != null) {
234248
requestFuture.completeExceptionally(throwable);
@@ -237,6 +251,7 @@ public CompletableFuture<Void> execute(AsyncExecuteRequest asyncRequest) {
237251

238252
AwsCrtAsyncHttpStreamAdapter crtToSdkAdapter =
239253
new AwsCrtAsyncHttpStreamAdapter(crtConn, requestFuture, asyncRequest, windowSize);
254+
HttpRequest crtRequest = toCrtRequest(uri, asyncRequest, crtToSdkAdapter);
240255

241256
// Submit the Request on this Connection
242257
invokeSafely(() -> crtConn.makeRequest(crtRequest, crtToSdkAdapter));
@@ -263,24 +278,17 @@ public void close() {
263278
*/
264279
public interface Builder extends SdkAsyncHttpClient.Builder<AwsCrtAsyncHttpClient.Builder> {
265280

266-
/**
267-
* The number of Threads to use in the EventLoop.
268-
* @param eventLoopSize The number of Threads to use in the EventLoop.
269-
* @return the builder of the method chaining.
270-
*/
271-
Builder eventLoopSize(int eventLoopSize);
272-
273281
/**
274282
* The AWS CRT TlsCipherPreference to use for this Client
275283
* @param tlsCipherPreference The AWS Common Runtime TlsCipherPreference
276-
* @return the builder of the method chaining.
284+
* @return The builder of the method chaining.
277285
*/
278286
Builder tlsCipherPreference(TlsCipherPreference tlsCipherPreference);
279287

280288
/**
281289
* Whether or not to Verify the Peer's TLS Certificate Chain.
282290
* @param verifyPeer true if the Certificate Chain should be validated, false if validation should be skipped.
283-
* @return the builder of the method chaining.
291+
* @return The builder of the method chaining.
284292
*/
285293
Builder verifyPeer(boolean verifyPeer);
286294

@@ -290,9 +298,23 @@ public interface Builder extends SdkAsyncHttpClient.Builder<AwsCrtAsyncHttpClien
290298
* the Subscriber to read more data.
291299
*
292300
* @param windowSize The AWS Common Runtime WindowSize
293-
* @return the builder of the method chaining.
301+
* @return The builder of the method chaining.
294302
*/
295303
Builder windowSize(int windowSize);
304+
305+
/**
306+
* The AWS CRT EventLoopGroup to use for this Client.
307+
* @param eventLoopGroup The AWS CRT EventLoopGroup to use for this client.
308+
* @return The builder of the method chaining.
309+
*/
310+
Builder eventLoopGroup(EventLoopGroup eventLoopGroup);
311+
312+
/**
313+
* The AWS CRT HostResolver to use for this Client.
314+
* @param hostResolver The AWS CRT HostResolver to use for this client.
315+
* @return The builder of the method chaining.
316+
*/
317+
Builder hostResolver(HostResolver hostResolver);
296318
}
297319

298320
/**
@@ -301,10 +323,11 @@ public interface Builder extends SdkAsyncHttpClient.Builder<AwsCrtAsyncHttpClien
301323
*/
302324
private static final class DefaultBuilder implements Builder {
303325
private final AttributeMap.Builder standardOptions = AttributeMap.builder();
304-
private int eventLoopSize = Runtime.getRuntime().availableProcessors();
305326
private TlsCipherPreference cipherPreference = TlsCipherPreference.TLS_CIPHER_SYSTEM_DEFAULT;
306327
private int windowSize = DEFAULT_STREAM_WINDOW_SIZE;
307328
private boolean verifyPeer = true;
329+
private EventLoopGroup eventLoopGroup;
330+
private HostResolver hostResolver;
308331

309332
private DefaultBuilder() {
310333
}
@@ -322,13 +345,6 @@ public SdkAsyncHttpClient buildWithDefaults(AttributeMap serviceDefaults) {
322345
.merge(SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS));
323346
}
324347

325-
@Override
326-
public Builder eventLoopSize(int eventLoopSize) {
327-
Validate.isPositive(eventLoopSize, "eventLoopSize");
328-
this.eventLoopSize = eventLoopSize;
329-
return this;
330-
}
331-
332348
@Override
333349
public Builder tlsCipherPreference(TlsCipherPreference tlsCipherPreference) {
334350
Validate.notNull(tlsCipherPreference, "cipherPreference");
@@ -350,5 +366,17 @@ public Builder windowSize(int windowSize) {
350366
this.windowSize = windowSize;
351367
return this;
352368
}
369+
370+
@Override
371+
public Builder eventLoopGroup(EventLoopGroup eventLoopGroup) {
372+
this.eventLoopGroup = eventLoopGroup;
373+
return this;
374+
}
375+
376+
@Override
377+
public Builder hostResolver(HostResolver hostResolver) {
378+
this.hostResolver = hostResolver;
379+
return this;
380+
}
353381
}
354382
}

0 commit comments

Comments
 (0)