Skip to content

Commit feebcd2

Browse files
committed
Create ConnectionHealthChecksConfiguration
1 parent 5e0266b commit feebcd2

File tree

4 files changed

+225
-9
lines changed

4 files changed

+225
-9
lines changed

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

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,25 @@ private AwsCrtAsyncHttpClient(DefaultBuilder builder, AttributeMap config) {
105105

106106
this.initialWindowSize = builder.initialWindowSize;
107107
this.maxConnectionsPerEndpoint = maxConns;
108-
this.monitoringOptions = builder.monitoringOptions;
108+
this.monitoringOptions = revolveHttpMonitoringOptions(builder.connectionHealthChecksConfiguration);
109109
this.maxConnectionIdleInMilliseconds = config.get(SdkHttpConfigurationOption.CONNECTION_MAX_IDLE_TIMEOUT).toMillis();
110110

111111
this.proxyOptions = buildProxyOptions(builder.proxyConfiguration);
112112
}
113113
}
114114

115+
private HttpMonitoringOptions revolveHttpMonitoringOptions(ConnectionHealthChecksConfiguration config) {
116+
if (config == null) {
117+
return null;
118+
}
119+
120+
HttpMonitoringOptions httpMonitoringOptions = new HttpMonitoringOptions();
121+
httpMonitoringOptions.setMinThroughputBytesPerSecond(config.minThroughputInBytesPerSecond());
122+
int seconds = (int) config.allowableThroughputFailureInterval().getSeconds();
123+
httpMonitoringOptions.setAllowableThroughputFailureIntervalSeconds(seconds);
124+
return httpMonitoringOptions;
125+
}
126+
115127
private HttpProxyOptions buildProxyOptions(ProxyConfiguration proxyConfiguration) {
116128
if (proxyConfiguration == null) {
117129
return null;
@@ -411,10 +423,25 @@ public interface Builder extends SdkAsyncHttpClient.Builder<AwsCrtAsyncHttpClien
411423
* If the connection falls below this threshold for a configurable amount of time,
412424
* then the connection is considered unhealthy and will be shut down.
413425
*
414-
* @param monitoringOptions The http monitoring options to use
426+
* @param healthChecksConfiguration The health checks config to use
427+
* @return The builder of the method chaining.
428+
*/
429+
Builder connectionHealthChecksConfiguration(ConnectionHealthChecksConfiguration healthChecksConfiguration);
430+
431+
/**
432+
* A convenience method to configure the health checks for for all connections established by this client.
433+
*
434+
* <p>
435+
* eg: you can set a throughput threshold for the a connection to be considered healthy.
436+
* If the connection falls below this threshold for a configurable amount of time,
437+
* then the connection is considered unhealthy and will be shut down.
438+
*
439+
* @param healthChecksConfigurationBuilder The health checks config builder to use
415440
* @return The builder of the method chaining.
441+
* @see #connectionHealthChecksConfiguration(ConnectionHealthChecksConfiguration)
416442
*/
417-
Builder connectionHealthChecksConfiguration(HttpMonitoringOptions monitoringOptions);
443+
Builder connectionHealthChecksConfiguration(Consumer<ConnectionHealthChecksConfiguration.Builder>
444+
healthChecksConfigurationBuilder);
418445

419446
/**
420447
* Configure the maximum amount of time that a connection should be allowed to remain open while idle.
@@ -433,7 +460,7 @@ private static final class DefaultBuilder implements Builder {
433460
private EventLoopGroup eventLoopGroup;
434461
private HostResolver hostResolver;
435462
private ProxyConfiguration proxyConfiguration;
436-
private HttpMonitoringOptions monitoringOptions;
463+
private ConnectionHealthChecksConfiguration connectionHealthChecksConfiguration;
437464

438465
private DefaultBuilder() {
439466
}
@@ -493,11 +520,19 @@ public Builder proxyConfiguration(ProxyConfiguration proxyConfiguration) {
493520
}
494521

495522
@Override
496-
public Builder connectionHealthChecksConfiguration(HttpMonitoringOptions monitoringOptions) {
497-
this.monitoringOptions = monitoringOptions;
523+
public Builder connectionHealthChecksConfiguration(ConnectionHealthChecksConfiguration monitoringOptions) {
524+
this.connectionHealthChecksConfiguration = monitoringOptions;
498525
return this;
499526
}
500527

528+
@Override
529+
public Builder connectionHealthChecksConfiguration(Consumer<ConnectionHealthChecksConfiguration.Builder>
530+
configurationBuilder) {
531+
ConnectionHealthChecksConfiguration.Builder builder = ConnectionHealthChecksConfiguration.builder();
532+
configurationBuilder.accept(builder);
533+
return connectionHealthChecksConfiguration(builder.build());
534+
}
535+
501536
@Override
502537
public Builder connectionMaxIdleTime(Duration connectionMaxIdleTime) {
503538
standardOptions.put(SdkHttpConfigurationOption.CONNECTION_MAX_IDLE_TIMEOUT, connectionMaxIdleTime);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.http.crt;
17+
18+
import java.time.Duration;
19+
import software.amazon.awssdk.annotations.SdkPublicApi;
20+
import software.amazon.awssdk.utils.Validate;
21+
22+
/**
23+
* Configuration that defines health checks for for all connections established by
24+
* the{@link ConnectionHealthChecksConfiguration}.
25+
*/
26+
@SdkPublicApi
27+
public final class ConnectionHealthChecksConfiguration {
28+
private final long minThroughputInBytesPerSecond;
29+
private final Duration allowableThroughputFailureInterval;
30+
31+
private ConnectionHealthChecksConfiguration(DefaultConnectionHealthChecksConfigurationBuilder builder) {
32+
this.minThroughputInBytesPerSecond = Validate.paramNotNull(builder.minThroughputInBytesPerSecond,
33+
"minThroughputInBytesPerSecond");
34+
this.allowableThroughputFailureInterval = Validate.isPositive(builder.allowableThroughputFailureIntervalSeconds,
35+
"allowableThroughputFailureIntervalSeconds");
36+
}
37+
38+
/**
39+
* @return the minimum amount of throughput, in bytes per second, for a connection to be considered healthy.
40+
*/
41+
public long minThroughputInBytesPerSecond() {
42+
return minThroughputInBytesPerSecond;
43+
}
44+
45+
/**
46+
* @return How long a connection is allowed to be unhealthy before getting shut down.
47+
*/
48+
public Duration allowableThroughputFailureInterval() {
49+
return allowableThroughputFailureInterval;
50+
}
51+
52+
public static Builder builder() {
53+
return new DefaultConnectionHealthChecksConfigurationBuilder();
54+
}
55+
56+
/**
57+
* A builder for {@link ConnectionHealthChecksConfiguration}.
58+
*
59+
* <p>All implementations of this interface are mutable and not thread safe.</p>
60+
*/
61+
public interface Builder {
62+
63+
/**
64+
* Sets a throughput threshold for connections. Throughput below this value will be considered unhealthy.
65+
*
66+
* @param minThroughputInBytesPerSecond minimum amount of throughput, in bytes per second, for a connection to be
67+
* considered healthy.
68+
* @return Builder
69+
*/
70+
Builder minThroughputInBytesPerSecond(Long minThroughputInBytesPerSecond);
71+
72+
/**
73+
* Sets how long a connection is allowed to be unhealthy before getting shut down.
74+
*
75+
* <p>
76+
* It only supports seconds precision
77+
*
78+
* @param allowableThroughputFailureIntervalSeconds How long a connection is allowed to be unhealthy
79+
* before getting shut down.
80+
* @return Builder
81+
*/
82+
Builder allowableThroughputFailureInterval(Duration allowableThroughputFailureIntervalSeconds);
83+
84+
ConnectionHealthChecksConfiguration build();
85+
}
86+
87+
/**
88+
* An SDK-internal implementation of {@link Builder}.
89+
*/
90+
private static final class DefaultConnectionHealthChecksConfigurationBuilder implements Builder {
91+
private Long minThroughputInBytesPerSecond;
92+
private Duration allowableThroughputFailureIntervalSeconds;
93+
94+
private DefaultConnectionHealthChecksConfigurationBuilder() {
95+
}
96+
97+
@Override
98+
public Builder minThroughputInBytesPerSecond(Long minThroughputInBytesPerSecond) {
99+
this.minThroughputInBytesPerSecond = minThroughputInBytesPerSecond;
100+
return this;
101+
}
102+
103+
@Override
104+
public Builder allowableThroughputFailureInterval(Duration allowableThroughputFailureIntervalSeconds) {
105+
this.allowableThroughputFailureIntervalSeconds = allowableThroughputFailureIntervalSeconds;
106+
return this;
107+
}
108+
109+
@Override
110+
public ConnectionHealthChecksConfiguration build() {
111+
return new ConnectionHealthChecksConfiguration(this);
112+
}
113+
}
114+
}

http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientSpiVerificationTest.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.github.tomakehurst.wiremock.junit.WireMockRule;
3131
import java.net.URI;
3232
import java.nio.ByteBuffer;
33+
import java.time.Duration;
3334
import java.util.Random;
3435
import java.util.concurrent.CompletableFuture;
3536
import java.util.concurrent.ExecutionException;
@@ -77,9 +78,11 @@ public void setup() throws Exception {
7778
hostResolver = new HostResolver(eventLoopGroup);
7879

7980
client = AwsCrtAsyncHttpClient.builder()
80-
.eventLoopGroup(eventLoopGroup)
81-
.hostResolver(hostResolver)
82-
.build();
81+
.eventLoopGroup(eventLoopGroup)
82+
.hostResolver(hostResolver)
83+
.connectionHealthChecksConfiguration(b -> b.minThroughputInBytesPerSecond(4068L)
84+
.allowableThroughputFailureInterval(Duration.ofSeconds(3)))
85+
.build();
8386
}
8487

8588
@After
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.http.crt;
17+
18+
19+
20+
import static org.assertj.core.api.Assertions.assertThat;
21+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
22+
23+
import java.time.Duration;
24+
import org.junit.Test;
25+
26+
public class ConnectionHealthChecksConfigurationTest {
27+
28+
@Test
29+
public void builder_allPropertiesSet() {
30+
ConnectionHealthChecksConfiguration connectionHealthChecksConfiguration =
31+
ConnectionHealthChecksConfiguration.builder()
32+
.minThroughputInBytesPerSecond(123l)
33+
.allowableThroughputFailureInterval(Duration.ofSeconds(1))
34+
.build();
35+
36+
assertThat(connectionHealthChecksConfiguration.minThroughputInBytesPerSecond()).isEqualTo(123);
37+
assertThat(connectionHealthChecksConfiguration.allowableThroughputFailureInterval()).isEqualTo(Duration.ofSeconds(1));
38+
}
39+
40+
@Test
41+
public void builder_nullMinThroughputInBytesPerSecond_shouldThrowException() {
42+
assertThatThrownBy(() ->
43+
ConnectionHealthChecksConfiguration.builder()
44+
.allowableThroughputFailureInterval(Duration.ofSeconds(1))
45+
.build()).hasMessageContaining("minThroughputInBytesPerSecond");
46+
}
47+
48+
@Test
49+
public void builder_nullAllowableThroughputFailureInterval() {
50+
assertThatThrownBy(() ->
51+
ConnectionHealthChecksConfiguration.builder()
52+
.minThroughputInBytesPerSecond(1L)
53+
.build()).hasMessageContaining("allowableThroughputFailureIntervalSeconds");
54+
}
55+
56+
@Test
57+
public void builder_negativeAllowableThroughputFailureInterval() {
58+
assertThatThrownBy(() ->
59+
ConnectionHealthChecksConfiguration.builder()
60+
.minThroughputInBytesPerSecond(1L)
61+
.allowableThroughputFailureInterval(Duration.ofSeconds(-1))
62+
.build()).hasMessageContaining("allowableThroughputFailureIntervalSeconds");
63+
}
64+
}

0 commit comments

Comments
 (0)