Verwenden Sie asynchrone Programmierung - AWS SDK for Java 2.x

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Verwenden Sie asynchrone Programmierung

Es AWS SDK for Java 2.x bietet asynchrone Clients mit nicht blockierender I/O-Unterstützung, die eine hohe Parallelität über einige Threads hinweg implementieren. Eine vollständige blockierungsfreie I/O kann jedoch nicht garantiert werden. In einigen Fällen kann ein asynchroner Client blockierende Aufrufe ausführen, z. B. beim Abrufen von Anmeldeinformationen, beim Signieren von Anfragen mit AWS Signature Version 4 (Sigv4) oder bei der Endpunkterkennung.

Synchrone Methoden blockieren die Ausführung Ihres Threads, bis der Client eine Antwort vom Service erhält. Asynchrone Methoden kehren sofort zurück. So haben Sie die Gewissheit, dass die Kontrolle an den aufrufenden Thread zurückgegeben wird, ohne auf eine Antwort zu warten.

Da eine asynchrone Methode zurückmeldet, bevor eine Antwort verfügbar ist, benötigen Sie einen Weg, an die Antwort zu gelangen, sobald diese bereitsteht. Die Methoden für asynchrone Clients in 2.x der AWS SDK for Java CompletableFuture Rückgabeobjekte, mit denen Sie auf die Antwort zugreifen können, wenn sie bereit ist.

Verwenden Sie einen asynchronen Client APIs

Die Signaturen asynchroner Clientmethoden sind dieselben wie bei synchronen Methoden, aber die asynchronen Methoden geben ein CompletableFutureObjekt zurück, das die Ergebnisse der asynchronen Operation in der future enthält. Wenn während der Ausführung der asynchronen Methode des SDK ein Fehler ausgelöst wird, wird der Fehler als ausgegeben. CompletionException

Ein Ansatz, den Sie verwenden können, um das Ergebnis zu erhalten, besteht darin, eine whenComplete() Methode mit dem vom SDK CompletableFuture zurückgegebenen Methodenaufruf zu verketten. Die whenComplete() Methode empfängt das Ergebnis oder ein Throwable-Objekt des Typs, CompletionException je nachdem, wie der asynchrone Aufruf abgeschlossen wurde. Sie geben eine Aktion an, um die Ergebnisse whenComplete() zu verarbeiten oder zu überprüfen, bevor sie an den aufrufenden Code zurückgegeben werden.

Wenn Sie etwas anderes als das von der SDK-Methode zurückgegebene Objekt zurückgeben möchten, verwenden Sie stattdessen die handle() Methode. Die handle() Methode verwendet dieselben Parameter wiewhenComplete(), aber Sie können das Ergebnis verarbeiten und ein Objekt zurückgeben.

Um zu warten, bis die asynchrone Kette abgeschlossen ist, und um die Ergebnisse der Fertigstellung abzurufen, können Sie die join() Methode aufrufen. Wenn das Throwable Objekt nicht in der Kette behandelt wurde, löst die join() Methode eine unkontrollierte Fehlermeldung aus, CompletionException die die ursprüngliche Ausnahme umschließt. Sie greifen auf die ursprüngliche Ausnahme mit zu. CompletionException#getCause() Sie können die CompletableFuture#get() Methode auch aufrufen, um die Abschlussergebnisse abzurufen. Die get() Methode kann jedoch geprüfte Ausnahmen auslösen.

Das folgende Beispiel zeigt zwei Varianten, wie Sie mit der listTables() Methode des asynchronen DynamoDB-Clients arbeiten können. Die Aktion, an die übergeben wurde, protokolliert whenComplete() lediglich eine erfolgreiche Antwort, wohingegen die handle() Version die Liste der Tabellennamen extrahiert und die Liste zurückgibt. In beiden Fällen wird, wenn in der asynchronen Kette ein Fehler generiert wird, der Fehler erneut ausgelöst, sodass der Client-Code die Möglichkeit hat, ihn zu behandeln.

Importe

import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; import software.amazon.awssdk.services.dynamodb.model.ListTablesRequest; import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse; import java.util.List; import java.util.concurrent.CompletableFuture;

Code

whenComplete() variation
public class DynamoDbAsyncListTables { public static void main(String[] args) { Region region = Region.US_EAST_1; DynamoDbAsyncClient dynamoDbAsyncClient = DynamoDbAsyncClient.builder().region(region).build(); try { ListTablesResponse listTablesResponse = listTablesWhenComplete(dynamoDbAsyncClient).join(); // The join() method may throw a CompletionException. if (listTablesResponse.hasTableNames()){ System.out.println("Table exist in this region: " + region.id()); } } catch (RuntimeException e) { // Handle as needed. Here we simply print out the class names. System.out.println(e.getClass()); // Prints 'class java.util.concurrent.CompletionException'. System.out.println(e.getCause().getClass()); // Prints 'class software.amazon.awssdk.services.dynamodb.model.DynamoDbException'. } } public static CompletableFuture<ListTablesResponse> listTablesWhenComplete(DynamoDbAsyncClient client) { return client.listTables(ListTablesRequest.builder().build()) .whenComplete((listTablesResponse, throwable) -> { if (listTablesResponse != null) { // Consume the response. System.out.println("The SDK's listTables method completed successfully."); } else { RuntimeException cause = (RuntimeException) throwable.getCause(); // If an error was thrown during the SDK's listTables method it is wrapped in a CompletionException. // The SDK throws only RuntimeExceptions, so this is a safe cast. System.out.println(cause.getMessage()); // Log error here, but rethrow so the calling code can handle as needed. throw cause; } }); }
handle() variation
public class DynamoDbAsyncListTables { public static void main(String[] args) { Region region = Region.US_EAST_1; DynamoDbAsyncClient dynamoDbAsyncClient = DynamoDbAsyncClient.builder().region(region).build(); try { List<String> tableNames = listTablesHandle(dynamoDbAsyncClient).join(); // The join() method may throw a CompletionException. tableNames.forEach(System.out::println); } catch (RuntimeException e) { // Handle as needed. Here we simply print out the class names. System.out.println(e.getClass()); // Prints 'class java.util.concurrent.CompletionException'. System.out.println(e.getCause().getClass()); // Prints 'class software.amazon.awssdk.services.dynamodb.model.DynamoDbException'. } } public static CompletableFuture<List<String>> listTablesHandle(DynamoDbAsyncClient client) { return client.listTables(ListTablesRequest.builder().build()) .handle((listTablesResponse, throwable) -> { if (listTablesResponse != null) { return listTablesResponse.tableNames(); // Return the list of table names. } else { RuntimeException cause = (RuntimeException) throwable.getCause(); // If an error was thrown during the SDK's listTables method it is wrapped in a CompletionException. // The SDK throws only RuntimeExceptions, so this is a safe cast. System.out.println(cause.getMessage()); // Log error here, but rethrow so the calling code can handle as needed. throw cause; } }); } }

Behandeln Sie das Streaming mit asynchronen Methoden

Bei asynchronen Methoden mit Streaming-Inhalten müssen Sie eine angeben, AsyncRequestBodyum den Inhalt inkrementell bereitzustellen, oder eine, um die Antwort AsyncResponseTransformerzu empfangen und zu verarbeiten.

Im folgenden Beispiel wird eine Datei asynchron hochgeladen, indem die Amazon S3 asynchrone Form des Vorgangs verwendet wird. PutObject

Importe

import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectResponse; import java.nio.file.Paths; import java.util.concurrent.CompletableFuture;

Code

/** * To run this AWS code example, ensure that you have setup your development environment, including your AWS credentials. * * For information, see this documentation topic: * * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class S3AsyncOps { public static void main(String[] args) { final String USAGE = "\n" + "Usage:\n" + " S3AsyncOps <bucketName> <key> <path>\n\n" + "Where:\n" + " bucketName - the name of the Amazon S3 bucket (for example, bucket1). \n\n" + " key - the name of the object (for example, book.pdf). \n" + " path - the local path to the file (for example, C:/AWS/book.pdf). \n" ; if (args.length != 3) { System.out.println(USAGE); System.exit(1); } String bucketName = args[0]; String key = args[1]; String path = args[2]; Region region = Region.US_WEST_2; S3AsyncClient client = S3AsyncClient.builder() .region(region) .build(); PutObjectRequest objectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(key) .build(); // Put the object into the bucket CompletableFuture<PutObjectResponse> future = client.putObject(objectRequest, AsyncRequestBody.fromFile(Paths.get(path)) ); future.whenComplete((resp, err) -> { try { if (resp != null) { System.out.println("Object uploaded. Details: " + resp); } else { // Handle error err.printStackTrace(); } } finally { // Only close the client when you are completely done with it client.close(); } }); future.join(); } }

Im folgenden Beispiel wird mithilfe der asynchronen Form der Operation eine Datei Amazon S3 von abgerufen. GetObject

Importe

import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import java.nio.file.Paths; import java.util.concurrent.CompletableFuture;

Code

/** * To run this AWS code example, ensure that you have setup your development environment, including your AWS credentials. * * For information, see this documentation topic: * * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class S3AsyncStreamOps { public static void main(String[] args) { final String USAGE = "\n" + "Usage:\n" + " S3AsyncStreamOps <bucketName> <objectKey> <path>\n\n" + "Where:\n" + " bucketName - the name of the Amazon S3 bucket (for example, bucket1). \n\n" + " objectKey - the name of the object (for example, book.pdf). \n" + " path - the local path to the file (for example, C:/AWS/book.pdf). \n" ; if (args.length != 3) { System.out.println(USAGE); System.exit(1); } String bucketName = args[0]; String objectKey = args[1]; String path = args[2]; Region region = Region.US_WEST_2; S3AsyncClient client = S3AsyncClient.builder() .region(region) .build(); GetObjectRequest objectRequest = GetObjectRequest.builder() .bucket(bucketName) .key(objectKey) .build(); CompletableFuture<GetObjectResponse> futureGet = client.getObject(objectRequest, AsyncResponseTransformer.toFile(Paths.get(path))); futureGet.whenComplete((resp, err) -> { try { if (resp != null) { System.out.println("Object downloaded. Details: "+resp); } else { err.printStackTrace(); } } finally { // Only close the client when you are completely done with it client.close(); } }); futureGet.join(); } }

Konfigurieren Sie erweiterte asynchrone Optionen

AWS SDK for Java 2.x verwendet Netty, ein asynchrones, ereignisgesteuertes Netzwerkanwendungs-Framework, um I/O-Threads zu verarbeiten. AWS SDK for Java 2.x erstellt ein ExecutorService Back-Netty, um die von der HTTP-Client-Anfrage an den Netty-Client zurückgegebenen Futures zu vervollständigen. Diese Abstraktion reduziert das Risiko, dass eine Anwendung den asynchronen Prozess unterbricht, wenn Entwickler Threads anhalten oder in den Ruhezustand versetzen. Standardmäßig erstellt jeder asynchrone Client einen Threadpool, der auf der Anzahl der Prozessoren basiert, und verwaltet die Aufgaben in einer Warteschlange innerhalb von. ExecutorService

Sie können ExecutorService beim Erstellen Ihres asynchronen Clients eine bestimmte JDK-Implementierung angeben. Das folgende Snippet erstellt einen ExecutorService mit einer festen Anzahl von Threads.

Code

S3AsyncClient clientThread = S3AsyncClient.builder() .asyncConfiguration( b -> b.advancedOption(SdkAdvancedAsyncClientOption .FUTURE_COMPLETION_EXECUTOR, Executors.newFixedThreadPool(10) ) ) .build();

Um die Leistung zu optimieren, können Sie Ihren eigenen Thread-Pool-Executor verwalten und ihn bei der Konfiguration Ihres Clients einbeziehen.

ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 50, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(<custom_value>), new ThreadFactoryBuilder() .threadNamePrefix("sdk-async-response").build()); // Allow idle core threads to time out executor.allowCoreThreadTimeOut(true); S3AsyncClient clientThread = S3AsyncClient.builder() .asyncConfiguration( b -> b.advancedOption(SdkAdvancedAsyncClientOption .FUTURE_COMPLETION_EXECUTOR, executor ) ) .build();