Получение исключения com.amazonaws.http.timers.client.SdkInterruptedException при выполнении приведенной ниже строки кода при развертывании как задания Spark в AWS EMR.
S3Object response = s3client.getObject(new GetObjectRequest(s3URI.getBucket(), s3URI.getKey()));
Версия SDK, код и трассировка стека указаны ниже. В чем может быть проблема и как ее решить?
Информация о версии
Зависимость
Код
public static ByteArrayOutputStream getS3Object(String path) {
AmazonS3 s3client = null;
try {
AmazonS3URI s3URI = new AmazonS3URI(path);
s3client = AmazonS3ClientBuilder.defaultClient();
S3Object response = s3client.getObject(new GetObjectRequest(s3URI.getBucket(), s3URI.getKey()));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = response.getObjectContent().read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
}
response.close();
return byteArrayOutputStream;
} catch (AbortedException | IOException e) {
e.printStackTrace();
System.err.println("AWS call interrupted retrying " + e);
} finally {
if (s3client != null) {
s3client.shutdown();
}
}
throw new RuntimeException("s3 object is null");
}
Трассировки стека
com.amazonaws.AbortedException:
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleInterruptedException(AmazonHttpClient.java:880)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:757)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:715)
at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:697)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:561)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:541)
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:5456)
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:5403)
at com.amazonaws.services.s3.AmazonS3Client.getObject(AmazonS3Client.java:1524)
com.example.S3Utils.getS3Object(S3Utils.java:78)
Caused by: com.amazonaws.http.timers.client.SdkInterruptedException
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.checkInterrupted(AmazonHttpClient.java:935)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.checkInterrupted(AmazonHttpClient.java:921)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1115)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:814)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:781)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:755)
... 53 more




Вы используете версию SDK, которая устарела, как указано в моем комментарии. Теперь, чтобы получить объект S3 с помощью AWS SDK для Java V2, вы можете использовать этот код. Если вы не знаете, как начать работу с V2, см. Руководство для разработчиков:
Руководство разработчика — AWS SDK для Java 2.x
package com.example.s3;
// snippet-start:[s3.java2.getobjectdata.main]
// snippet-start:[s3.java2.getobjectdata.import]
import software.amazon.awssdk.core.ResponseBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
// snippet-end:[s3.java2.getobjectdata.import]
/**
* Before running this Java V2 code example, set up your development
* environment, including your credentials.
*
* For more information, see the following documentation topic:
*
* https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
*/
public class GetObjectData {
public static void main(String[] args) {
final String usage = """
Usage:
<bucketName> <keyName> <path>
Where:
bucketName - The Amazon S3 bucket name.\s
keyName - The key name.\s
path - The path where the file is written to.\s
""";
if (args.length != 3) {
System.out.println(usage);
System.exit(1);
}
String bucketName = args[0];
String keyName = args[1];
String path = args[2];
Region region = Region.US_EAST_1;
S3Client s3 = S3Client.builder()
.region(region)
.build();
getObjectBytes(s3, bucketName, keyName, path);
}
public static void getObjectBytes(S3Client s3, String bucketName, String keyName, String path) {
try {
GetObjectRequest objectRequest = GetObjectRequest
.builder()
.key(keyName)
.bucket(bucketName)
.build();
ResponseBytes<GetObjectResponse> objectBytes = s3.getObjectAsBytes(objectRequest);
byte[] data = objectBytes.asByteArray();
// Write the data to a local file.
File myFile = new File(path);
OutputStream os = new FileOutputStream(myFile);
os.write(data);
System.out.println("Successfully obtained bytes from an S3 object");
os.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (S3Exception e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
}
}
// snippet-end:[s3.java2.getobjectdata.main]
Вы можете найти POM в примере кода AWS на Github здесь:
https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/s3
Спасибо @smac2020. У нас есть другой код, использующий AWS SDK для Java v1.x. Будут ли внесены какие-либо изменения в этот код для перехода с AWS SDK для версии 1.x на версию 2.x?
Да, существует руководство по миграции. docs.aws.amazon.com/sdk-for-java/latest/developer-guide/…. Вам следует как можно скорее заменить все версии V1 на V2.
мы попробовали обновить версию aws sdk (software.amazon.awssdk:s3:2.24.5) и использовали ваш код. Теперь мы видим это исключение software.amazon.awssdk.core.exception.SdkClientException: Unable to load credentials from any of the providers in the chain....Interrupted waiting to refresh a cached value., InstanceProfileCredentialsProvider(): Interrupted waiting to refresh a cached value.. Вариант использования: мы вызываем API с этим объектом S3. Мы получаем это исключение после того, как сервер возвращает 500 — внутренняя ошибка сервера, и мы пытаемся получить объект S3. В чем может быть проблема?
Это означает, что ваши учетные данные не могут быть найдены «software.amazon.awssdk.core.Exception.SdkClientException: невозможно загрузить учетные данные от любого из поставщиков в цепочке». Чтобы настроить свои учетные данные, см. docs.aws.amazon.com/sdk-for-java/latest/developer-guide/…
Мы перебираем список путей S3, затем получаем текущий объект S3, а затем загружаем этот объект S3 в виде файла, состоящего из нескольких частей, вызывающего API. Учитывая пять путей к объектам S3, если API завершается с ошибкой сервера 500 при попытке использовать третий объект S3, мы сталкиваемся с этим исключением при попытке возобновить работу с четвертым объектом S3. (Примечание. Экземпляр настраивается с помощью роли IAM, и мы не настраиваем учетные данные явным образом). Также пробовал использовать политику повтора (СТАНДАРТ) на клиенте S3, но проблема осталась та же. В чем может быть проблема?
Вы используете AWS SDK для Java V1. Эта версия SDK скоро устареет. aws.amazon.com/blogs/developer/…. Вам следует обновиться до V2 как можно скорее. Ниже я опубликую код, который вы должны использовать.