mirror of https://github.com/apache/druid.git
Add retries for building S3 client (#16438)
* Add retries for building S3 client * Use S3Utils instead of RetryUtils * Add test
This commit is contained in:
parent
4bfc186153
commit
d1100a6f63
|
@ -92,6 +92,10 @@ public class S3Utils
|
||||||
} else if (e instanceof SdkClientException && e.getMessage().contains("Unable to execute HTTP request")) {
|
} else if (e instanceof SdkClientException && e.getMessage().contains("Unable to execute HTTP request")) {
|
||||||
// This is likely due to a temporary DNS issue and can be retried.
|
// This is likely due to a temporary DNS issue and can be retried.
|
||||||
return true;
|
return true;
|
||||||
|
} else if (e instanceof SdkClientException && e.getMessage().contains("Unable to find a region via the region provider chain")) {
|
||||||
|
// This can happen sometimes when AWS isn't able to obtain the credentials for some service:
|
||||||
|
// https://github.com/aws/aws-sdk-java/issues/2285
|
||||||
|
return true;
|
||||||
} else if (e instanceof AmazonClientException) {
|
} else if (e instanceof AmazonClientException) {
|
||||||
return AWSClientUtil.isClientExceptionRecoverable((AmazonClientException) e);
|
return AWSClientUtil.isClientExceptionRecoverable((AmazonClientException) e);
|
||||||
} else {
|
} else {
|
||||||
|
@ -101,8 +105,8 @@ public class S3Utils
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retries S3 operations that fail due to io-related exceptions. Service-level exceptions (access denied, file not
|
* Retries S3 operations that fail intermittently (due to io-related exceptions, during obtaining credentials, etc).
|
||||||
* found, etc) are not retried.
|
* Service-level exceptions (access denied, file not found, etc) are not retried.
|
||||||
*/
|
*/
|
||||||
public static <T> T retryS3Operation(Task<T> f) throws Exception
|
public static <T> T retryS3Operation(Task<T> f) throws Exception
|
||||||
{
|
{
|
||||||
|
@ -110,8 +114,9 @@ public class S3Utils
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retries S3 operations that fail due to io-related exceptions. Service-level exceptions (access denied, file not
|
* Retries S3 operations that fail intermittently (due to io-related exceptions, during obtaining credentials, etc).
|
||||||
* found, etc) are not retried. Also provide a way to set maxRetries that can be useful, i.e. for testing.
|
* Service-level exceptions (access denied, file not found, etc) are not retried.
|
||||||
|
* Also provide a way to set maxRetries that can be useful, i.e. for testing.
|
||||||
*/
|
*/
|
||||||
public static <T> T retryS3Operation(Task<T> f, int maxRetries) throws Exception
|
public static <T> T retryS3Operation(Task<T> f, int maxRetries) throws Exception
|
||||||
{
|
{
|
||||||
|
|
|
@ -204,7 +204,15 @@ public class ServerSideEncryptingAmazonS3
|
||||||
throw new ISE("S3StorageConfig cannot be null!");
|
throw new ISE("S3StorageConfig cannot be null!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ServerSideEncryptingAmazonS3(amazonS3ClientBuilder.build(), s3StorageConfig.getServerSideEncryption());
|
AmazonS3 amazonS3Client;
|
||||||
|
try {
|
||||||
|
amazonS3Client = S3Utils.retryS3Operation(() -> amazonS3ClientBuilder.build());
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ServerSideEncryptingAmazonS3(amazonS3Client, s3StorageConfig.getServerSideEncryption());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.apache.druid.storage.s3;
|
package org.apache.druid.storage.s3;
|
||||||
|
|
||||||
|
import com.amazonaws.SdkClientException;
|
||||||
import com.amazonaws.services.s3.model.AmazonS3Exception;
|
import com.amazonaws.services.s3.model.AmazonS3Exception;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -108,4 +109,25 @@ public class S3UtilsTest
|
||||||
);
|
);
|
||||||
Assert.assertEquals(maxRetries, count.get());
|
Assert.assertEquals(maxRetries, count.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRetryWithSdkClientException() throws Exception
|
||||||
|
{
|
||||||
|
final int maxRetries = 3;
|
||||||
|
final AtomicInteger count = new AtomicInteger();
|
||||||
|
S3Utils.retryS3Operation(
|
||||||
|
() -> {
|
||||||
|
if (count.incrementAndGet() >= maxRetries) {
|
||||||
|
return "hey";
|
||||||
|
} else {
|
||||||
|
throw new SdkClientException(
|
||||||
|
"Unable to find a region via the region provider chain. "
|
||||||
|
+ "Must provide an explicit region in the builder or setup environment to supply a region."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxRetries
|
||||||
|
);
|
||||||
|
Assert.assertEquals(maxRetries, count.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue