Skip to content

Commit 28d190b

Browse files
HADOOP-18845. Add ability to configure s3 connection ttl using fs.s3a.connection.ttl (#5948)
Contributed By: Mukund Thakur
1 parent 11404c5 commit 28d190b

File tree

5 files changed

+66
-2
lines changed

5 files changed

+66
-2
lines changed

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/Constants.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,17 @@ private Constants() {
154154
public static final String MAXIMUM_CONNECTIONS = "fs.s3a.connection.maximum";
155155
public static final int DEFAULT_MAXIMUM_CONNECTIONS = 96;
156156

157+
/**
158+
* Configuration option to configure expiration time of
159+
* s3 http connection from the connection pool in milliseconds: {@value}.
160+
*/
161+
public static final String CONNECTION_TTL = "fs.s3a.connection.ttl";
162+
163+
/**
164+
* Default value for {@code CONNECTION_TTL}: {@value}.
165+
*/
166+
public static final long DEFAULT_CONNECTION_TTL = 5 * 60_000;
167+
157168
// connect to s3 over ssl?
158169
public static final String SECURE_CONNECTIONS =
159170
"fs.s3a.connection.ssl.enabled";

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/Invoker.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ public <T> T retryUntranslated(
462462
do {
463463
try {
464464
if (retryCount > 0) {
465-
LOG.debug("retry #{}", retryCount);
465+
LOG.debug("{} retry #{}", text, retryCount);
466466
}
467467
// execute the operation, returning if successful
468468
return operation.apply();
@@ -471,7 +471,8 @@ public <T> T retryUntranslated(
471471
}
472472
// you only get here if the operation didn't complete
473473
// normally, hence caught != null
474-
474+
LOG.debug("{} ; {}, ", text, caught.toString());
475+
LOG.trace("", caught);
475476
// translate the exception into an IOE for the retry logic
476477
IOException translated;
477478
if (caught instanceof IOException) {

hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,8 @@ public static void initConnectionSettings(Configuration conf,
12991299
ClientConfiguration awsConf) throws IOException {
13001300
awsConf.setMaxConnections(intOption(conf, MAXIMUM_CONNECTIONS,
13011301
DEFAULT_MAXIMUM_CONNECTIONS, 1));
1302+
awsConf.setConnectionTTL(longOption(conf, CONNECTION_TTL,
1303+
DEFAULT_CONNECTION_TTL, -1));
13021304
initProtocolSettings(conf, awsConf);
13031305
awsConf.setMaxErrorRetry(intOption(conf, MAX_ERROR_RETRIES,
13041306
DEFAULT_MAX_ERROR_RETRIES, 0));

hadoop-tools/hadoop-aws/src/site/markdown/tools/hadoop-aws/troubleshooting_s3a.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,6 +1782,26 @@ will attempt to retry the operation; it may just be a transient event. If there
17821782
are many such exceptions in logs, it may be a symptom of connectivity or network
17831783
problems.
17841784

1785+
The above error could be because of a stale http connections. The default value in AWS
1786+
SDK is set to -1 (infinite) which means the connection will be reused indefinitely.
1787+
We have introduced a new config `fs.s3a.connection.ttl` to configure this.
1788+
Tuning this setting down (together with an appropriately-low setting for Java's DNS cache TTL)
1789+
ensures that your application will quickly rotate over to new IP addresses when the
1790+
service begins announcing them through DNS, at the cost of having to re-establish new
1791+
connections more frequently.
1792+
1793+
```xml
1794+
<property>
1795+
<name>fs.s3a.connection.ttl</name>
1796+
<value>300000</value>
1797+
<description>
1798+
Expiration time for a connection in the connection pool in milliseconds.
1799+
When a connection is retrieved from the connection pool,
1800+
this parameter is checked to see if the connection can be reused.
1801+
Default value is 5 minutes.
1802+
</description>
1803+
</property>
1804+
```
17851805
### `AWSBadRequestException` IllegalLocationConstraintException/The unspecified location constraint is incompatible
17861806

17871807
```

hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/ITestS3AConfiguration.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import org.apache.hadoop.fs.contract.ContractTestUtils;
3232
import org.apache.hadoop.fs.s3native.S3xLoginHelper;
3333
import org.apache.hadoop.test.GenericTestUtils;
34+
35+
import org.assertj.core.api.Assertions;
3436
import org.junit.Assert;
3537
import org.junit.Rule;
3638
import org.junit.Test;
@@ -511,6 +513,34 @@ public void testConfOptionPropagationToFS() throws Exception {
511513
assertOptionEquals(updated, "fs.s3a.propagation", "propagated");
512514
}
513515

516+
@Test(timeout = 10_000L)
517+
public void testConnectTtlPropagation() throws Exception {
518+
Configuration config = new Configuration(false);
519+
ClientConfiguration awsConf = new ClientConfiguration();
520+
initConnectionSettings(config, awsConf);
521+
Assertions.assertThat(awsConf.getConnectionTTL())
522+
.describedAs("connection ttl should be set to default value as" +
523+
" %s is not set", CONNECTION_TTL)
524+
.isEqualTo(DEFAULT_CONNECTION_TTL);
525+
long connectionTtlTestVal = 1000;
526+
config.setLong(CONNECTION_TTL, connectionTtlTestVal);
527+
initConnectionSettings(config, awsConf);
528+
Assertions.assertThat(awsConf.getConnectionTTL())
529+
.describedAs("%s not propagated to aws conf", CONNECTION_TTL)
530+
.isEqualTo(connectionTtlTestVal);
531+
532+
long connectionTtlTestVal1 = -1;
533+
config.setLong(CONNECTION_TTL, connectionTtlTestVal1);
534+
initConnectionSettings(config, awsConf);
535+
Assertions.assertThat(awsConf.getConnectionTTL())
536+
.describedAs("%s not propagated to aws conf", CONNECTION_TTL)
537+
.isEqualTo(connectionTtlTestVal1);
538+
539+
long connectionTtlTestVal2 = -100;
540+
config.setLong(CONNECTION_TTL, connectionTtlTestVal2);
541+
intercept(IllegalArgumentException.class, () -> initConnectionSettings(config, awsConf));
542+
}
543+
514544
@Test(timeout = 10_000L)
515545
public void testS3SpecificSignerOverride() throws IOException {
516546
ClientConfiguration clientConfiguration = null;

0 commit comments

Comments
 (0)