Usa la programmazione asincrona - AWS SDK for Java 2.x

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Usa la programmazione asincrona

AWS SDK for Java 2.x Dispone di client asincroni con supporto I/O non bloccante che implementano un'elevata concorrenza su pochi thread. Tuttavia, l'I/O totale non bloccante non è garantito. Il client asincrono può eseguire chiamate di blocco in alcuni casi, ad esempio nel recupero delle credenziali, nella firma delle richieste tramite AWS Signature Version 4 (SigV4) o nel rilevamento degli endpoint.

I metodi sincroni bloccano l'esecuzione del thread finché il client non riceve una risposta dal servizio. I metodi asincroni terminano immediatamente, riassegnando il controllo al thread chiamante senza attendere una risposta.

Poiché un metodo asincrono termina prima che sia disponibile una risposta, occorre un modo per ottenere la risposta quando è pronta. I metodi per il client asincrono nella versione 2.x degli oggetti AWS SDK for Java CompletableFuture restituiti che consentono di accedere alla risposta quando è pronta.

Usa un client asincrono APIs

Le firme dei metodi client asincroni sono le stesse della loro controparte sincrona, ma i metodi asincroni restituiscono un CompletableFutureoggetto che contiene i risultati dell'operazione asincrona futura. Se viene generato un errore durante l'esecuzione del metodo asincrono dell'SDK, l'errore viene generato come. CompletionException

Un approccio che puoi utilizzare per ottenere il risultato consiste nel concatenare un whenComplete() metodo alla chiamata al metodo SDK restituitaCompletableFuture. Il whenComplete() metodo riceve il risultato o un oggetto Throwable di tipo CompletionException a seconda del completamento della chiamata asincrona. Si esegue un'azione per elaborare o controllare whenComplete() i risultati prima che vengano restituiti al codice chiamante.

Se vuoi restituire qualcosa di diverso dall'oggetto restituito dal metodo SDK, usa invece il handle() metodo. Il handle() metodo accetta gli stessi parametriwhenComplete(), ma potete elaborare il risultato e restituire un oggetto.

Per attendere il completamento della catena asincrona e recuperare i risultati del completamento, potete chiamare il metodo. join() Se l'Throwableoggetto non è stato gestito nella catena, il join() metodo genera un valore CompletionException deselezionato che racchiude l'eccezione originale. Si accede all'eccezione originale con. CompletionException#getCause() Puoi anche chiamare il CompletableFuture#get() metodo per ottenere i risultati del completamento. Il get() metodo, tuttavia, può generare eccezioni verificate.

L'esempio seguente mostra due varianti di come lavorare con il listTables() metodo del client asincrono DynamoDB. L'azione passata a registra whenComplete() semplicemente una risposta riuscita, mentre la handle() versione estrae l'elenco dei nomi delle tabelle e restituisce l'elenco. In entrambi i casi, se viene generato un errore nella catena asincrona, l'errore viene generato nuovamente in modo che il codice client abbia la possibilità di gestirlo.

Importazioni

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;

Codice

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; } }); } }

Gestisci lo streaming con metodi asincroni

Per i metodi asincroni con contenuti in streaming, è necessario fornire il contenuto in modo incrementale oppure un codice AsyncRequestBodyper ricevere ed elaborare la risposta AsyncResponseTransformer.

L'esempio seguente carica un file in modalità asincrona utilizzando la forma Amazon S3 asincrona dell'operazione. PutObject

Importazioni

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;

Codice

/** * 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(); } }

L'esempio seguente ottiene un file Amazon S3 da utilizzando la forma asincrona dell'operazione. GetObject

Importazioni

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;

Codice

/** * 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(); } }

Configura le opzioni asincrone avanzate

La AWS SDK for Java 2.x utilizza Netty, un framework applicativo di rete asincrono basato sugli eventi, per gestire i thread di I/O. Il AWS SDK for Java 2.x crea un ExecutorService behind Netty, per completare i futures restituiti dalla richiesta del client HTTP al client Netty. Questa astrazione riduce il rischio che un'applicazione interrompa il processo asincrono se gli sviluppatori scelgono di arrestare o sospendere i thread. Per impostazione predefinita, ogni client asincrono crea un pool di thread in base al numero di processori e gestisce le attività in una coda all'interno di. ExecutorService

È possibile specificare un'implementazione JDK specifica quando si crea il client asincrono. ExecutorService Il seguente frammento crea un file con un ExecutorService numero fisso di thread.

Codice

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

Per ottimizzare le prestazioni, puoi gestire il tuo esecutore del pool di thread e includerlo nella configurazione del client.

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();