Programmazione di DynamoDB con AWS SDK for Java 2.x - Amazon DynamoDB

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à.

Programmazione di DynamoDB con AWS SDK for Java 2.x

Questa guida alla programmazione fornisce un orientamento per i programmatori che desiderano utilizzare Amazon DynamoDB con Java. La guida copre diversi concetti, tra cui livelli di astrazione, gestione della configurazione, gestione degli errori, controllo delle politiche di ripetizione dei tentativi e gestione di keep-alive.

Informazioni su AWS SDK for Java 2.x

È possibile accedere a DynamoDB da Java utilizzando il file ufficiale. AWS SDK for Java La versione SDK per Java è disponibile in due versioni: 1.x e 2.x. La versione end-of-support 1.x è stata annunciata il 12 gennaio 2024. Entrerà in modalità manutenzione il 31 luglio 2024 e scadrà end-of-support il 31 dicembre 2025. Per un nuovo sviluppo, consigliamo vivamente di utilizzare 2.x, che è stato rilasciato per la prima volta nel 2018. Questa guida si rivolge esclusivamente alla versione 2.x e si concentra solo sulle parti SDK relative a DynamoDB.

Per informazioni sulla manutenzione e il supporto per AWS SDKs, consulta la politica di manutenzione di AWS SDK and Tools e la matrice di supporto della versione Tools nella AWS SDKs and Tools Reference AWS SDKsGuide.

AWS SDK for Java 2.x Si tratta di un'importante riscrittura del codice base 1.x. La versione SDK per Java 2.x supporta le moderne funzionalità Java, come l'I/O non bloccante introdotto in Java 8. The SDK for Java 2.x aggiunge anche il supporto per implementazioni HTTP client collegabili per fornire maggiore flessibilità di connessione di rete e opzioni di configurazione.

Un cambiamento evidente tra SDK for Java 1.x e for Java 2.x è l'SDKuso di un nuovo nome di pacchetto. Java 1.x SDK utilizza il nome del com.amazonaws pacchetto, mentre Java 2.x lo utilizza. SDK software.amazon.awssdk Allo stesso modo, gli artefatti Maven per Java 1.x SDK utilizzano, mentre gli artefatti Java 2.x utilizzano com.amazonaws groupId il. SDK software.amazon.awssdk groupId

Importante

La versione AWS SDK for Java 1.x ha un pacchetto DynamoDB denominato. com.amazonaws.dynamodbv2 La «v2" nel nome del pacchetto non indica che sia per Java 2 (J2SE). Piuttosto, «v2" indica che il pacchetto supporta la seconda versione di DynamoDB di basso livello API anziché la versione originale di basso livello. API

Support per le versioni Java

AWS SDK for Java 2.x Fornisce il supporto completo per le versioni Java con supporto a lungo termine (LTS).

Nozioni di base su AWS SDK for Java 2.x

Il seguente tutorial mostra come usare Apache Maven per definire le dipendenze per Java 2.x. SDK Questo tutorial mostra anche come scrivere il codice che si connette a DynamoDB per elencare le tabelle DynamoDB disponibili. Il tutorial contenuto in questa guida si basa sul tutorial Get started with AWS SDK for Java 2.x nella Developer Guide.AWS SDK for Java 2.x Abbiamo modificato questo tutorial per effettuare chiamate a DynamoDB anziché ad Amazon S3.

Fase 1: Configurazione per questo tutorial

Prima di iniziare questo tutorial, è necessario quanto segue:

  • Autorizzazione ad accedere a DynamoDB.

  • Un ambiente di sviluppo Java configurato con accesso Single Sign-On all'utilizzo di. AWS servizi Portale di accesso AWS

Per configurare questo tutorial, segui le istruzioni riportate nella panoramica sulla configurazione nella Guida per gli AWS SDK for Java 2.x sviluppatori. Dopo aver configurato l'ambiente di sviluppo con l'accesso Single Sign-On per Java SDK e aver avuto una sessione attiva sul portale di AWS accesso, continuate con la Fase 2 di questo tutorial.

Fase 2: Creare il progetto

Per creare il progetto per questo tutorial, esegui un comando Maven che richiede input su come configurare il progetto. Dopo aver inserito e confermato tutti gli input, Maven completa la creazione del progetto creando un pom.xml file e creando file Java stub.

  1. Apri un terminale o una finestra del prompt dei comandi e accedi a una directory a tua scelta, ad esempio la tua cartella o. Desktop Home

  2. Immettete il seguente comando nel terminale, quindi premete Invio.

    mvn archetype:generate \ -DarchetypeGroupId=software.amazon.awssdk \ -DarchetypeArtifactId=archetype-app-quickstart \ -DarchetypeVersion=2.22.0
  3. Per ogni prompt, inserisci il valore elencato nella seconda colonna.

    Prompt Valore da inserire
    Define value for property 'service': dynamodb
    Define value for property 'httpClient': apache-client
    Define value for property 'nativeImage': false
    Define value for property 'credentialProvider' identity-center
    Define value for property 'groupId': org.example
    Define value for property 'artifactId': getstarted
    Define value for property 'version' 1.0-SNAPSHOT: <Enter>
    Define value for property 'package' org.example: <Enter>
  4. Dopo aver inserito l'ultimo valore, Maven elenca le scelte che hai fatto. Per confermare, inserisci Y. In alternativa, inserisci N, quindi inserisci nuovamente le tue scelte.

Maven crea una cartella di progetto denominata getstarted in base al artifactId valore che hai inserito. All'interno della getstarted cartella, trova un file con un nome README.md che puoi rivedere, un pom.xml file e una src directory.

Maven crea il seguente albero di cartelle.

getstarted ├── README.md ├── pom.xml └── src ├── main │ ├── java │ │ └── org │ │ └── example │ │ ├── App.java │ │ ├── DependencyFactory.java │ │ └── Handler.java │ └── resources │ └── simplelogger.properties └── test └── java └── org └── example └── HandlerTest.java 10 directories, 7 files

Quanto segue mostra il contenuto del file di progetto. pom.xml

La dependencyManagement sezione contiene una dipendenza da e la AWS SDK for Java 2.xdependencies sezione ha una dipendenza per DynamoDB. La specificazione di queste dipendenze impone a Maven di includere i file pertinenti nel percorso della classe Java. .jar Per impostazione predefinita, AWS SDK non include tutte le classi per tutti. AWS servizi Per DynamoDB, se utilizzi l'interfaccia di basso livello, dovresti avere una dipendenza dall'artefatto. dynamodb Oppure, se si utilizza l'interfaccia di alto livello, sull'artefatto. dynamodb-enhanced Se non includi le dipendenze pertinenti, il codice non può essere compilato. Il progetto utilizza Java 1.8 a causa del 1.8 valore delle proprietà maven.compiler.source andmaven.compiler.target.

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>getstarted</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.shade.plugin.version>3.2.1</maven.shade.plugin.version> <maven.compiler.plugin.version>3.6.1</maven.compiler.plugin.version> <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version> <aws.java.sdk.version>2.22.0</aws.java.sdk.version> <-------- SDK version picked up from archetype version. <slf4j.version>1.7.28</slf4j.version> <junit5.version>5.8.1</junit5.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>${aws.java.sdk.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>dynamodb</artifactId> <-------- DynamoDB dependency <exclusions> <exclusion> <groupId>software.amazon.awssdk</groupId> <artifactId>netty-nio-client</artifactId> </exclusion> <exclusion> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>sso</artifactId> <-------- Required for identity center authentication. </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>ssooidc</artifactId> <-------- Required for identity center authentication. </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> <-------- HTTP client specified. <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>${slf4j.version}</version> </dependency> <!-- Needed to adapt Apache Commons Logging used by Apache HTTP Client to Slf4j to avoid ClassNotFoundException: org.apache.commons.logging.impl.LogFactoryImpl during runtime --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <!-- Test Dependencies --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>${junit5.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven.compiler.plugin.version}</version> </plugin> </plugins> </build> </project>

Passaggio 3: scrivere il codice

Il codice seguente mostra la App classe creata da Maven. Il main metodo è il punto di ingresso nell'applicazione, che crea un'istanza della Handler classe e quindi ne sendRequest chiama il metodo.

package org.example; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class App { private static final Logger logger = LoggerFactory.getLogger(App.class); public static void main(String... args) { logger.info("Application starts"); Handler handler = new Handler(); handler.sendRequest(); logger.info("Application ends"); } }

La DependencyFactory classe creata da Maven contiene il metodo dynamoDbClient factory che crea e restituisce un'istanza. DynamoDbClient L'DynamoDbClientistanza utilizza un'istanza del client basato su Apache. HTTP Questo perché hai specificato apache-client quando Maven ti ha chiesto quale client usare. HTTP

Il codice seguente mostra la classe DependencyFactory.

package org.example; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; /** * The module containing all dependencies required by the {@link Handler}. */ public class DependencyFactory { private DependencyFactory() {} /** * @return an instance of DynamoDbClient */ public static DynamoDbClient dynamoDbClient() { return DynamoDbClient.builder() .httpClientBuilder(ApacheHttpClient.builder()) .build(); } }

La Handler classe contiene la logica principale del programma. Quando Handler viene creata un'istanza di nella App classe, DependencyFactory fornisce il DynamoDbClient servizio client. Il codice utilizza l'DynamoDbClientistanza per chiamare DynamoDB.

Maven genera la seguente Handler classe con un commento. TODO Il passaggio successivo del tutorial sostituisce il TODOcommento con il codice.

package org.example; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; public class Handler { private final DynamoDbClient dynamoDbClient; public Handler() { dynamoDbClient = DependencyFactory.dynamoDbClient(); } public void sendRequest() { // TODO: invoking the API calls using dynamoDbClient. } }

Per compilare la logica, sostituisci l'intero contenuto della Handler classe con il codice seguente. Il sendRequest metodo viene compilato e vengono aggiunte le importazioni necessarie.

Il codice seguente utilizza l'DynamoDbClientistanza per recuperare un elenco di tabelle esistenti. Se esistono tabelle per un determinato account e Regione AWS, il codice utilizza l'Loggeristanza per registrare i nomi di queste tabelle.

package org.example; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse; public class Handler { private final DynamoDbClient dynamoDbClient; public Handler() { dynamoDbClient = DependencyFactory.dynamoDbClient(); } public void sendRequest() { Logger logger = LoggerFactory.getLogger(Handler.class); logger.info("calling the DynamoDB API to get a list of existing tables"); ListTablesResponse response = dynamoDbClient.listTables(); if (!response.hasTableNames()) { logger.info("No existing tables found for the configured account & region"); } else { response.tableNames().forEach(tableName -> logger.info("Table: " + tableName)); } } }

Fase 4: Compilare ed eseguire l'applicazione

Dopo aver creato il progetto e aver contenuto la Handler classe completa, create ed eseguite l'applicazione.

  1. Assicurati di avere una AWS IAM Identity Center sessione attiva. Per confermare, esegui il comando AWS Command Line Interface (AWS CLI) aws sts get-caller-identity e controlla la risposta. Se non hai una sessione attiva, consulta Accedi utilizzando il AWS CLI per le istruzioni.

  2. Apri un terminale o una finestra del prompt dei comandi e accedi alla directory getstarted del progetto.

  3. Per creare il tuo progetto, esegui il seguente comando:

    mvn clean package
  4. Per eseguire l'applicazione, esegui il seguente comando:

    mvn exec:java -Dexec.mainClass="org.example.App"

Dopo aver visualizzato il file, eliminate l'oggetto, quindi eliminate il bucket.

Riuscito

Se il tuo progetto Maven è stato creato ed eseguito senza errori, allora congratulazioni! Hai creato con successo la tua prima applicazione Java utilizzando SDK per Java 2.x.

Rimozione

Per ripulire le risorse che hai creato durante questo tutorial, elimina la cartella getstarted del progetto.

Revisione della AWS SDK for Java 2.x documentazione

La Guida per gli AWS SDK for Java 2.x sviluppatori copre tutti gli aspetti di SDK Across All AWS servizi. Ti consigliamo di leggere i seguenti argomenti:

  • Migrazione dalla versione 1.x alla 2.x: include una spiegazione dettagliata delle differenze tra 1.x e 2.x. Questo argomento contiene anche istruzioni su come utilizzare entrambe le versioni principali. side-by-side

  • Guida DynamoDB per Java SDK 2.x: mostra come eseguire le operazioni di base di DynamoDB: creazione di una tabella, manipolazione di elementi e recupero di elementi. Questi esempi utilizzano l'interfaccia di basso livello. Java ha diverse interfacce, come spiegato nella sezione seguente:. Interfacce supportate

Suggerimento

Dopo aver esaminato questi argomenti, aggiungi il riferimento ai segnalibri.AWS SDK for Java 2.x API Copre tutto AWS servizi e ti consigliamo di utilizzarlo come API riferimento principale.

Interfacce supportate

AWS SDK for Java 2.x Supporta le seguenti interfacce, a seconda del livello di astrazione desiderato.

Interfaccia di basso livello

L'interfaccia di basso livello fornisce una one-to-one mappatura del servizio sottostante. API Ogni API DynamoDB è disponibile tramite questa interfaccia. Ciò significa che l'interfaccia di basso livello può fornire funzionalità complete, ma è spesso più dettagliata e complessa da usare. Ad esempio, è necessario utilizzare .s() le funzioni per contenere le stringhe e le .n() funzioni per contenere i numeri. Il seguente esempio di PutIteminserisce un elemento utilizzando l'interfaccia di basso livello.

import org.slf4j.*; import software.amazon.awssdk.http.crt.AwsCrtHttpClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.*; import java.util.Map; public class PutItem { // Create a DynamoDB client with the default settings connected to the DynamoDB // endpoint in the default region based on the default credentials provider chain. private static final DynamoDbClient DYNAMODB_CLIENT = DynamoDbClient.create(); private static final Logger LOGGER = LoggerFactory.getLogger(PutItem.class); private void putItem() { PutItemResponse response = DYNAMODB_CLIENT.putItem(PutItemRequest.builder() .item(Map.of( "pk", AttributeValue.builder().s("123").build(), "sk", AttributeValue.builder().s("cart#123").build(), "item_data", AttributeValue.builder().s("YourItemData").build(), "inventory", AttributeValue.builder().n("500").build() // ... more attributes ... )) .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) .tableName("YourTableName") .build()); LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)"); } }

Interfaccia di alto livello

L'interfaccia di alto livello di AWS SDK for Java 2.x si chiama DynamoDB Enhanced Client. Questa interfaccia offre un'esperienza di creazione del codice più idiomatica.

Il client avanzato offre un modo per mappare tra le classi di dati lato client e le tabelle DynamoDB progettate per archiviare tali dati. È possibile definire le relazioni tra le tabelle e le relative classi di modello corrispondenti nel codice. Quindi, puoi fare affidamento su SDK per gestire la manipolazione dei tipi di dati. Per ulteriori informazioni sul client avanzato, consulta DynamoDB Enhanced API Client nella AWS SDK for Java 2.x Developer Guide.

L'esempio seguente PutItemutilizza l'interfaccia di alto livello. In questo esempio, DynamoDbBean named YourItem crea un file TableSchema che ne consente l'uso diretto come input per la putItem() chiamata.

import org.slf4j.*; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.*; import software.amazon.awssdk.enhanced.dynamodb.model.*; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class DynamoDbEnhancedClientPutItem { private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<YourItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromBean(YourItem.class)); private static final Logger LOGGER = LoggerFactory.getLogger(PutItem.class); private void putItem() { PutItemEnhancedResponse<YourItem> response = DYNAMODB_TABLE.putItemWithResponse(PutItemEnhancedRequest.builder(YourItem.class) .item(new YourItem("123", "cart#123", "YourItemData", 500)) .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) .build()); LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)"); } @DynamoDbBean public static class YourItem { public YourItem() {} public YourItem(String pk, String sk, String itemData, int inventory) { this.pk = pk; this.sk = sk; this.itemData = itemData; this.inventory = inventory; } private String pk; private String sk; private String itemData; private int inventory; @DynamoDbPartitionKey public void setPk(String pk) { this.pk = pk; } public String getPk() { return pk; } @DynamoDbSortKey public void setSk(String sk) { this.sk = sk; } public String getSk() { return sk; } public void setItemData(String itemData) { this.itemData = itemData; } public String getItemData() { return itemData; } public void setInventory(int inventory) { this.inventory = inventory; } public int getInventory() { return inventory; } } }

La AWS SDK for Java 1.x ha una propria interfaccia di alto livello, a cui spesso si fa riferimento dalla sua classe principale. DynamoDBMapper AWS SDK for Java 2.x È pubblicato in un pacchetto separato (e artefatto Maven) denominato. software.amazon.awssdk.enhanced.dynamodb Java 2.x SDK viene spesso indicato con la sua classe principale. DynamoDbEnhancedClient

Interfaccia di alto livello che utilizza classi di dati immutabili

La funzionalità di mappatura del API client avanzato DynamoDB funziona anche con classi di dati immutabili. Una classe immutabile ha solo getter e richiede una classe builder che viene utilizzata per creare istanze della classe. SDK L'immutabilità in Java è uno stile comunemente usato che gli sviluppatori possono utilizzare per creare classi prive di effetti collaterali. Queste classi hanno un comportamento più prevedibile in applicazioni multithread complesse. Invece di utilizzare l'@DynamoDbBeanannotazione come mostrato inHigh-level interface example, le classi immutabili utilizzano l'@DynamoDbImmutableannotazione, che accetta la classe builder come input.

L'esempio seguente utilizza la classe builder DynamoDbEnhancedClientImmutablePutItem come input per creare uno schema di tabella. L'esempio fornisce quindi lo schema come input per la PutItemAPIchiamata.

import org.slf4j.*; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.model.*; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class DynamoDbEnhancedClientImmutablePutItem { private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<YourImmutableItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromImmutableClass(YourImmutableItem.class)); private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedClientImmutablePutItem.class); private void putItem() { PutItemEnhancedResponse<YourImmutableItem> response = DYNAMODB_TABLE.putItemWithResponse(PutItemEnhancedRequest.builder(YourImmutableItem.class) .item(YourImmutableItem.builder() .pk("123") .sk("cart#123") .itemData("YourItemData") .inventory(500) .build()) .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) .build()); LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)"); } }

L'esempio seguente mostra la classe di dati immutabile.

@DynamoDbImmutable(builder = YourImmutableItem.YourImmutableItemBuilder.class) class YourImmutableItem { private final String pk; private final String sk; private final String itemData; private final int inventory; public YourImmutableItem(YourImmutableItemBuilder builder) { this.pk = builder.pk; this.sk = builder.sk; this.itemData = builder.itemData; this.inventory = builder.inventory; } public static YourImmutableItemBuilder builder() { return new YourImmutableItemBuilder(); } @DynamoDbPartitionKey public String getPk() { return pk; } @DynamoDbSortKey public String getSk() { return sk; } public String getItemData() { return itemData; } public int getInventory() { return inventory; } static final class YourImmutableItemBuilder { private String pk; private String sk; private String itemData; private int inventory; private YourImmutableItemBuilder() {} public YourImmutableItemBuilder pk(String pk) { this.pk = pk; return this; } public YourImmutableItemBuilder sk(String sk) { this.sk = sk; return this; } public YourImmutableItemBuilder itemData(String itemData) { this.itemData = itemData; return this; } public YourImmutableItemBuilder inventory(int inventory) { this.inventory = inventory; return this; } public YourImmutableItem build() { return new YourImmutableItem(this); } } }

Interfaccia di alto livello che utilizza classi di dati immutabili e librerie di generazione boilerplate di terze parti

Le classi di dati immutabili (mostrate nell'esempio precedente) richiedono del codice standard. Ad esempio, la logica getter e setter sulle classi di dati, oltre alle classi. Builder Le librerie di terze parti, come Project Lombok, possono aiutarti a generare quel tipo di codice standard. La riduzione della maggior parte del codice standard consente di limitare la quantità di codice necessaria per lavorare con classi di dati immutabili e il. AWS SDK Ciò si traduce ulteriormente in una migliore produttività e leggibilità del codice. Per ulteriori informazioni, consulta Utilizzare librerie di terze parti, come Lombok, nella Guida per gli AWS SDK for Java 2.x sviluppatori.

L'esempio seguente dimostra come Project Lombok semplifica il codice necessario per utilizzare il client avanzato DynamoDB. API

import org.slf4j.*; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.model.*; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class DynamoDbEnhancedClientImmutableLombokPutItem { private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<YourImmutableLombokItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromImmutableClass(YourImmutableLombokItem.class)); private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedClientImmutableLombokPutItem.class); private void putItem() { PutItemEnhancedResponse<YourImmutableLombokItem> response = DYNAMODB_TABLE.putItemWithResponse(PutItemEnhancedRequest.builder(YourImmutableLombokItem.class) .item(YourImmutableLombokItem.builder() .pk("123") .sk("cart#123") .itemData("YourItemData") .inventory(500) .build()) .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) .build()); LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)"); } }

L'esempio seguente mostra l'oggetto dati immutabile della classe di dati immutabili.

import lombok.*; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.*; @Builder @DynamoDbImmutable(builder = YourImmutableLombokItem.YourImmutableLombokItemBuilder.class) @Value public class YourImmutableLombokItem { @Getter(onMethod_=@DynamoDbPartitionKey) String pk; @Getter(onMethod_=@DynamoDbSortKey) String sk; String itemData; int inventory; }

La YourImmutableLombokItem classe utilizza le seguenti annotazioni fornite da Project Lombok e da: AWS SDK

  • @Builder — Produce un generatore complesso APIs per le classi di dati fornito da Project Lombok.

  • @ DynamoDbImmutable — Identifica la DynamoDbImmutable classe come annotazione di entità mappabile DynamoDB che fornisce. AWS SDK

  • @Value — La variante immutabile di. @Data Per impostazione predefinita, tutti i campi vengono resi privati e definitivi e i setter non vengono generati. Project Lombok fornisce questa annotazione.

Interfaccia del documento

L'interfaccia AWS SDK for Java 2.x Document evita la necessità di specificare i descrittori dei tipi di dati. I tipi di dati sono impliciti nella semantica dei dati stessi. Questa interfaccia Document è simile alla AWS SDK for Java 1.x, interfaccia Document, ma con un'interfaccia riprogettata.

Di seguito Document interface example viene PutItem illustrata la chiamata espressa utilizzando l'interfaccia Document. L'esempio utilizza anche EnhancedDocument. Per eseguire comandi su una tabella DynamoDB utilizzando il API documento avanzato, è necessario innanzitutto associare la tabella allo schema della tabella dei documenti per creare un DynamoDBTable oggetto risorsa. Il generatore di schemi per tabelle di documenti richiede i provider principali di convertitori di chiavi di indice e attributi.

È possibile utilizzare AttributeConverterProvider.defaultProvider() per convertire gli attributi del documento di tipi predefiniti. È possibile modificare il comportamento predefinito generale con un'AttributeConverterProviderimplementazione personalizzata. È inoltre possibile modificare il convertitore per un singolo attributo. La guida di riferimento di AWS SDKs and Tools fornisce maggiori dettagli ed esempi su come utilizzare i convertitori personalizzati. Il loro utilizzo principale è per gli attributi delle classi di dominio che non dispongono di un convertitore predefinito. Utilizzando un convertitore personalizzato, è possibile fornire loro SDK le informazioni necessarie per scrivere o leggere su DynamoDB.

import org.slf4j.*; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; import software.amazon.awssdk.enhanced.dynamodb.model.*; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class DynamoDbEnhancedDocumentClientPutItem { private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<EnhancedDocument> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.documentSchemaBuilder() .addIndexPartitionKey(TableMetadata.primaryIndexName(),"pk", AttributeValueType.S) .addIndexSortKey(TableMetadata.primaryIndexName(), "sk", AttributeValueType.S) .attributeConverterProviders(AttributeConverterProvider.defaultProvider()) .build()); private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedDocumentClientPutItem.class); private void putItem() { PutItemEnhancedResponse<EnhancedDocument> response = DYNAMODB_TABLE.putItemWithResponse( PutItemEnhancedRequest.builder(EnhancedDocument.class) .item( EnhancedDocument.builder() .attributeConverterProviders(AttributeConverterProvider.defaultProvider()) .putString("pk", "123") .putString("sk", "cart#123") .putString("item_data", "YourItemData") .putNumber("inventory", 500) .build()) .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) .build()); LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)"); } }

Per convertire JSON i documenti da e verso i tipi di dati nativi di Amazon DynamoDB, puoi utilizzare i seguenti metodi di utilità:

Confronto delle interfacce con un esempio Query

Questa sezione mostra la stessa Querychiamata espressa utilizzando le varie interfacce. Per ottimizzare i risultati di queste interrogazioni, tenete presente quanto segue:

  • DynamoDB ha come target un valore specifico della chiave di partizione, quindi è necessario specificare completamente la chiave di partizione.

  • Per fare in modo che la query abbia come target solo gli articoli del carrello, la chiave di ordinamento contiene un'espressione di condizione chiave che utilizza. begins_with

  • In genere limitiamo limit() la richiesta a un massimo di 100 articoli restituiti.

  • Abbiamo impostato il valore scanIndexForward su false. I risultati vengono restituiti nell'ordine di UTF -8 byte, il che di solito significa che l'articolo del carrello con il numero più basso viene restituito per primo. Impostando il valore scanIndexForward su false, invertiamo l'ordine e l'articolo del carrello con il numero più alto viene restituito per primo.

  • Applichiamo un filtro per rimuovere qualsiasi risultato che non corrisponde ai criteri. I dati filtrati consumano la capacità di lettura indipendentemente dal fatto che l'articolo corrisponda al filtro.

Esempio Queryutilizzando l'interfaccia di basso livello

L'esempio seguente esegue una query su una tabella denominata YourTableName utilizzando un. keyConditionExpression Ciò limita la query a un valore di chiave di partizione e a un valore di chiave di ordinamento specifici che iniziano con un valore di prefisso specifico. Queste condizioni chiave limitano la quantità di dati letti da DynamoDB. Infine, la query applica un filtro sui dati recuperati da DynamoDB utilizzando un. filterExpression

import org.slf4j.*; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.*; import java.util.Map; public class Query { // Create a DynamoDB client with the default settings connected to the DynamoDB // endpoint in the default region based on the default credentials provider chain. private static final DynamoDbClient DYNAMODB_CLIENT = DynamoDbClient.builder().build(); private static final Logger LOGGER = LoggerFactory.getLogger(Query.class); private static void query() { QueryResponse response = DYNAMODB_CLIENT.query(QueryRequest.builder() .expressionAttributeNames(Map.of("#name", "name")) .expressionAttributeValues(Map.of( ":pk_val", AttributeValue.fromS("id#1"), ":sk_val", AttributeValue.fromS("cart#"), ":name_val", AttributeValue.fromS("SomeName"))) .filterExpression("#name = :name_val") .keyConditionExpression("pk = :pk_val AND begins_with(sk, :sk_val)") .limit(100) .scanIndexForward(false) .tableName("YourTableName") .build()); LOGGER.info("nr of items: " + response.count()); LOGGER.info("First item pk: " + response.items().get(0).get("pk")); LOGGER.info("First item sk: " + response.items().get(0).get("sk")); } }
Esempio Queryutilizzando l'interfaccia Document

L'esempio seguente esegue una query su una tabella denominata YourTableName utilizzando l'interfaccia Document.

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; import software.amazon.awssdk.enhanced.dynamodb.model.*; import java.util.Map; public class DynamoDbEnhancedDocumentClientQuery { // Create a DynamoDB client with the default settings connected to the DynamoDB // endpoint in the default region based on the default credentials provider chain. private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<EnhancedDocument> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.documentSchemaBuilder() .addIndexPartitionKey(TableMetadata.primaryIndexName(),"pk", AttributeValueType.S) .addIndexSortKey(TableMetadata.primaryIndexName(), "sk", AttributeValueType.S) .attributeConverterProviders(AttributeConverterProvider.defaultProvider()) .build()); private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedDocumentClientQuery.class); private void query() { PageIterable<EnhancedDocument> response = DYNAMODB_TABLE.query(QueryEnhancedRequest.builder() .filterExpression(Expression.builder() .expression("#name = :name_val") .expressionNames(Map.of("#name", "name")) .expressionValues(Map.of(":name_val", AttributeValue.fromS("SomeName"))) .build()) .limit(100) .queryConditional(QueryConditional.sortBeginsWith(Key.builder() .partitionValue("id#1") .sortValue("cart#") .build())) .scanIndexForward(false) .build()); LOGGER.info("nr of items: " + response.items().stream().count()); LOGGER.info("First item pk: " + response.items().iterator().next().getString("pk")); LOGGER.info("First item sk: " + response.items().iterator().next().getString("sk")); } }
Esempio Queryutilizzando l'interfaccia di alto livello

L'esempio seguente esegue una query su una tabella denominata YourTableName utilizzando il client avanzato DynamoDB. API

import org.slf4j.*; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.*; import software.amazon.awssdk.enhanced.dynamodb.model.*; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import java.util.Map; public class DynamoDbEnhancedClientQuery { private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<YourItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromBean(DynamoDbEnhancedClientQuery.YourItem.class)); private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedClientQuery.class); private void query() { PageIterable<YourItem> response = DYNAMODB_TABLE.query(QueryEnhancedRequest.builder() .filterExpression(Expression.builder() .expression("#name = :name_val") .expressionNames(Map.of("#name", "name")) .expressionValues(Map.of(":name_val", AttributeValue.fromS("SomeName"))) .build()) .limit(100) .queryConditional(QueryConditional.sortBeginsWith(Key.builder() .partitionValue("id#1") .sortValue("cart#") .build())) .scanIndexForward(false) .build()); LOGGER.info("nr of items: " + response.items().stream().count()); LOGGER.info("First item pk: " + response.items().iterator().next().getPk()); LOGGER.info("First item sk: " + response.items().iterator().next().getSk()); } @DynamoDbBean public static class YourItem { public YourItem() {} public YourItem(String pk, String sk, String name) { this.pk = pk; this.sk = sk; this.name = name; } private String pk; private String sk; private String name; @DynamoDbPartitionKey public void setPk(String pk) { this.pk = pk; } public String getPk() { return pk; } @DynamoDbSortKey public void setSk(String sk) { this.sk = sk; } public String getSk() { return sk; } public void setName(String name) { this.name = name; } public String getName() { return name; } } }
Interfaccia di alto livello che utilizza classi di dati immutabili

Quando si esegue un'operazione Query con le classi di dati immutabili di alto livello, il codice è lo stesso dell'esempio di interfaccia di alto livello, ad eccezione della costruzione della classe di entità o. YourItem YourImmutableItem Per ulteriori informazioni, consulta l'esempio. PutItem

Interfaccia di alto livello che utilizza classi di dati immutabili e librerie di generazione boilerplate di terze parti

Quando si esegue un'operazione Query con le classi di dati immutabili di alto livello, il codice è lo stesso dell'esempio di interfaccia di alto livello, ad eccezione della costruzione della classe di entità o. YourItem YourImmutableLombokItem Per ulteriori informazioni, consulta l'esempio. PutItem

Esempi di codice aggiuntivi

Per ulteriori esempi di utilizzo di DynamoDB con SDK for Java 2.x, fate riferimento ai seguenti repository di esempi di codice:

Programmazione sincrona e asincrona

AWS SDK for Java 2.x Fornisce client sincroni e asincroni per, AWS servizi come DynamoDB.

DynamoDbEnhancedClientLe classi DynamoDbClient and forniscono metodi sincroni che bloccano l'esecuzione del thread finché il client non riceve una risposta dal servizio. Questo client è il modo più semplice per interagire con DynamoDB se non sono necessarie operazioni asincrone.

DynamoDbEnhancedAsyncClientLe classi DynamoDbAsyncClient and forniscono metodi asincroni che ritornano immediatamente e restituiscono il controllo al thread chiamante senza attendere una risposta. Il client non bloccante presenta un vantaggio che sfrutta per un'elevata concorrenza su pochi thread, il che consente una gestione efficiente delle richieste di I/O con risorse di elaborazione minime. Ciò migliora il throughput e la reattività.

AWS SDK for Java 2.x Utilizza il supporto nativo per I/O non bloccanti. La versione AWS SDK for Java 1.x doveva simulare I/O non bloccanti.

I metodi sincroni ritornano prima che sia disponibile una risposta, quindi è necessario un modo per ottenere la risposta quando è pronta. I metodi asincroni in AWS SDK for Java restituiscono un CompletableFutureoggetto che contiene i risultati delle operazioni asincrone future. Quando chiamate get() o join() su questi CompletableFuture oggetti, il codice si blocca finché il risultato non è disponibile. Se li chiami contemporaneamente alla richiesta, il comportamento è simile a una semplice chiamata sincrona.

Per ulteriori informazioni sulla programmazione asincrona, consulta Use asynchronous programming nella Developer Guide.AWS SDK for Java 2.x

HTTPclienti

Per supportare ogni cliente, esiste un HTTP client che gestisce la comunicazione con AWS servizi. Puoi collegare HTTP client alternativi, scegliendone uno che abbia le caratteristiche più adatte alla tua applicazione. Alcuni sono più leggeri, altri hanno più opzioni di configurazione.

Alcuni HTTP client supportano solo l'uso sincrono, mentre altri supportano solo l'uso asincrono. Per un diagramma di flusso che può aiutarti a selezionare il HTTP client ottimale per il tuo carico di lavoro, consulta i consigli per i HTTPclienti nella Guida per gli sviluppatori.AWS SDK for Java 2.x

L'elenco seguente presenta alcuni dei possibili HTTP client:

Client basato su HTTP Apache

La ApacheHttpClientclasse supporta client di servizio sincroni. È il HTTP client predefinito per l'uso sincrono. Per informazioni sulla configurazione della ApacheHttpClient classe, consulta Configurare il HTTP client basato su Apache nella Guida per gli sviluppatori.AWS SDK for Java 2.x

URLConnectionclient basato HTTP

La UrlConnectionHttpClientclasse è un'altra opzione per i client sincroni. Si carica più velocemente rispetto al HTTP client basato su Apache, ma ha meno funzionalità. Per informazioni sulla configurazione della UrlConnectionHttpClient classe, consulta Configure the URLConnection based HTTP client nella Developer Guide.AWS SDK for Java 2.x

Client basato su Netty HTTP

La NettyNioAsyncHttpClient classe supporta client asincroni. È la scelta predefinita per l'uso asincrono. Per informazioni sulla configurazione della NettyNioAsyncHttpClient classe, consulta Configurare il HTTP client basato su Netty nella Guida per gli sviluppatori.AWS SDK for Java 2.x

AWS CRTclient basato HTTP

Le nuove AwsCrtHttpClient e AwsCrtAsyncHttpClient le classi delle librerie AWS Common Runtime (CRT) sono altre opzioni che supportano client sincroni e asincroni. Rispetto ad altri clienti, offre: HTTP AWS CRT

  • Tempo di SDK avvio più rapido

  • Ingombro di memoria ridotto

  • Tempo di latenza ridotto

  • Gestione dello stato della connessione

  • DNSbilanciamento del carico

Per informazioni sulla configurazione delle AwsCrtAsyncHttpClient classi AwsCrtHttpClient and, consulta Configure the AWS CRT based HTTP client nella AWS SDK for Java 2.x Developer Guide.

Il HTTP client AWS CRT basato non è l'impostazione predefinita perché ciò comprometterebbe la compatibilità con le versioni precedenti delle applicazioni esistenti. Tuttavia, per DynamoDB consigliamo di utilizzare AWS CRT il client HTTP basato sia per usi sincronizzati che asincroni.

Per un'introduzione al HTTP client AWS CRT basato, vedi Annuncio della disponibilità del AWS CRT HTTP client nel blog AWS SDK for Java 2.x sugli strumenti per sviluppatori.AWS

Configurazione di un client HTTP

Durante la configurazione di un client, puoi fornire varie opzioni di configurazione, tra cui:

  • Impostazione dei timeout per diversi aspetti delle chiamate. API

  • Attivazione di TCP Keep-Alive.

  • Controllo della politica dei tentativi in caso di errori.

  • Specificare gli attributi di esecuzione che le istanze di Execution Interceptor possono modificare. Gli intercettori di esecuzione possono scrivere codice che intercetta l'esecuzione delle richieste e delle risposte. API Ciò consente di eseguire attività come la pubblicazione di metriche e la modifica delle richieste in corso.

  • Aggiungere o manipolare le intestazioni. HTTP

  • Abilitazione del monitoraggio delle metriche delle prestazioni lato client. L'utilizzo di questa funzionalità ti aiuta a raccogliere metriche sui client di servizio nella tua applicazione e ad analizzare l'output in Amazon CloudWatch.

  • Specificare un servizio esecutore alternativo da utilizzare per la pianificazione di attività, come tentativi di riprova asincroni e attività di timeout.

È possibile controllare la configurazione fornendo un oggetto alla classe client del servizio. ClientOverrideConfigurationBuilder Lo vedrai in alcuni esempi di codice nelle sezioni seguenti.

ClientOverrideConfigurationFornisce scelte di configurazione standard. I diversi HTTP client collegabili hanno anche possibilità di configurazione specifiche per l'implementazione.

Configurazione del timeout

È possibile regolare la configurazione del client per controllare vari timeout relativi alle chiamate di servizio. DynamoDB offre latenze inferiori rispetto ad altri. AWS servizi Pertanto, potresti voler modificare queste proprietà per ridurre i valori di timeout in modo da poter fallire rapidamente in caso di problemi di rete.

È possibile personalizzare il comportamento relativo alla latenza utilizzando ClientOverrideConfiguration il client DynamoDB o modificando le opzioni di configurazione dettagliate sull'implementazione client sottostante. HTTP

È possibile configurare le seguenti proprietà di impatto utilizzando: ClientOverrideConfiguration

  • apiCallAttemptTimeout— Il tempo di attesa necessario per il completamento di un singolo tentativo di HTTP richiesta prima di rinunciare e scadere.

  • apiCallTimeout— La quantità di tempo a disposizione del client per eseguire completamente una API chiamata. Ciò include l'esecuzione del gestore delle richieste che consiste in tutte le HTTP richieste, compresi i nuovi tentativi.

AWS SDK for Java 2.x Fornisce valori predefiniti per alcune opzioni di timeout, come il timeout della connessione e i timeout del socket. SDKNon fornisce valori predefiniti per i timeout delle chiamate o i timeout dei singoli tentativi di API chiamata. API Se questi timeout non sono impostati inClientOverrideConfiguration, SDK utilizza invece il valore di timeout del socket per il timeout complessivo della chiamata. API Il timeout del socket ha un valore predefinito di 30 secondi.

RetryMode

Un'altra configurazione relativa alla configurazione del timeout da prendere in considerazione è l'oggetto di RetryMode configurazione. Questo oggetto di configurazione contiene una raccolta di comportamenti relativi ai tentativi.

Il SDK for Java 2.x supporta le seguenti modalità di riprova:

  • legacy— La modalità di riprova predefinita se non la si modifica esplicitamente. Questa modalità di riprova è specifica di Java. SDK È caratterizzato da un massimo di tre tentativi, o più per servizi come DynamoDB, che dispone di un massimo di otto tentativi.

  • standard— Denominato «standard» perché è più coerente con gli altri. AWS SDKs Questa modalità attende un periodo di tempo casuale compreso tra 0 ms e 1.000 ms per il primo tentativo. Se è necessario un altro tentativo, questa modalità seleziona un altro tempo casuale da 0 ms a 1.000 ms e lo moltiplica per due. Se è necessario un altro tentativo, esegue la stessa scelta casuale moltiplicata per quattro e così via. Ogni attesa è limitata a 20 secondi. Questa modalità esegue nuovi tentativi su un numero maggiore di condizioni di errore rilevate rispetto alla legacy modalità. Per DynamoDB, esegue fino a un massimo di tre tentativi, a meno che non si esegua l'override con. numRetries

  • adaptive— Si basa sulla standard modalità e limita dinamicamente la frequenza delle AWS richieste per massimizzare la percentuale di successo. Ciò può avvenire a scapito della latenza delle richieste. Non consigliamo la modalità di riprova adattiva quando la latenza prevedibile è importante.

È possibile trovare una definizione estesa di queste modalità di ripetizione nell'argomento sul comportamento Riprova nella Guida di riferimento agli strumenti e agli strumenti.AWS SDKs

Criteri relativi ai nuovi tentativi

Tutte le RetryMode configurazioni hanno un RetryPolicy, che è costruito sulla base di una o più RetryConditionconfigurazioni. TokenBucketRetryConditionÈ particolarmente importante per il comportamento di ripetizione dell'implementazione del client SDK DynamoDB. Questa condizione limita il numero di tentativi effettuati utilizzando un algoritmo SDK token bucket. A seconda della modalità di ripetizione selezionata, le eccezioni di limitazione possono o meno sottrarre token da. TokenBucket

Quando un client rileva un errore riutilizzabile, ad esempio un'eccezione di limitazione o un errore temporaneo del server, riprova automaticamente la richiesta. SDK È possibile controllare quante volte e con quale rapidità si verificano questi nuovi tentativi.

Quando si configura un client, è possibile fornire un client RetryPolicy che supporti i seguenti parametri:

  • numRetries— Il numero massimo di tentativi da applicare prima che una richiesta venga considerata fallita. Il valore predefinito è 8 indipendentemente dalla modalità di ripetizione utilizzata.

    avvertimento

    Assicuratevi di modificare questo valore predefinito dopo aver preso in debita considerazione.

  • backoffStrategyBackoffStrategyDa applicare ai nuovi tentativi, FullJitterBackoffStrategyessendo la strategia predefinita. Questa strategia esegue un ritardo esponenziale tra tentativi aggiuntivi in base al numero o ai tentativi correnti, un ritardo di base e un tempo massimo di backoff. Quindi aggiunge il jitter per fornire un po' di casualità. Il ritardo di base utilizzato nel ritardo esponenziale è di 25 ms indipendentemente dalla modalità di ripetizione.

  • retryConditionRetryConditionDetermina se riprovare o meno una richiesta. Per impostazione predefinita, riprova un set specifico di codici di HTTP stato ed eccezioni che ritiene riutilizzabili. Per la maggior parte delle situazioni, la configurazione predefinita dovrebbe essere sufficiente.

Il codice seguente fornisce una politica di riprova alternativa. Specifica un totale di cinque tentativi (sei richieste totali). Il primo tentativo deve avvenire dopo un ritardo di circa 100 ms, con ogni tentativo aggiuntivo che raddoppia tale tempo in modo esponenziale, fino a un ritardo massimo di un secondo.

DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(ClientOverrideConfiguration.builder() .retryPolicy(RetryPolicy.builder() .backoffStrategy(FullJitterBackoffStrategy.builder() .baseDelay(Duration.ofMillis(100)) .maxBackoffTime(Duration.ofSeconds(1)) .build()) .numRetries(5) .build()) .build()) .build();

DefaultsMode

Le proprietà di timeout che ClientOverrideConfiguration e RetryMode non gestiscono sono in genere configurate implicitamente specificando a. DefaultsMode

La AWS SDK for Java 2.x (versione 2.17.102 o successiva) ha introdotto il supporto per. DefaultsMode Questa funzionalità fornisce un set di valori predefiniti per le impostazioni configurabili più comuni, come le impostazioni di HTTP comunicazione, il comportamento dei tentativi, le impostazioni regionali degli endpoint del servizio e, potenzialmente, qualsiasi configurazione correlata. SDK Quando si utilizza questa funzionalità, è possibile ottenere nuove impostazioni di configurazione predefinite personalizzate per scenari di utilizzo comuni.

Le modalità predefinite sono standardizzate in tutti i. AWS SDKs Il SDK for Java 2.x supporta le seguenti modalità predefinite:

  • legacy— Fornisce impostazioni predefinite che variano di base AWS SDK e che esistevano prima che DefaultsMode venissero stabilite.

  • standard— Fornisce impostazioni predefinite non ottimizzate per la maggior parte degli scenari.

  • in-region— Si basa sulla modalità standard e include impostazioni personalizzate per le applicazioni che effettuano chiamate AWS servizi dall'interno della stessa. Regione AWS

  • cross-region— Si basa sulla modalità standard e include impostazioni con timeout elevati per le applicazioni che effettuano chiamate AWS servizi in una regione diversa.

  • mobile— Si basa sulla modalità standard e include impostazioni con timeout elevati personalizzate per applicazioni mobili con latenze più elevate.

  • auto— Si basa sulla modalità standard e include funzionalità sperimentali. I SDK tentativi di scoprire l'ambiente di runtime per determinare automaticamente le impostazioni appropriate. Il rilevamento automatico è basato sull'euristica e non fornisce una precisione del 100%. Se non è possibile determinare l'ambiente di esecuzione, viene utilizzata la modalità standard. Il rilevamento automatico potrebbe interrogare i metadati dell'istanza e i dati utente, il che potrebbe introdurre latenza. Se la latenza di avvio è fondamentale per la tua applicazione, ti consigliamo invece di sceglierne una esplicita. DefaultsMode

È possibile configurare la modalità predefinita nei seguenti modi:

  • Direttamente su un client, tramite. AwsClientBuilder.Builder#defaultsMode(DefaultsMode)

  • Su un profilo di configurazione, tramite la proprietà del file di defaults_mode profilo.

  • A livello globale, tramite la proprietà aws.defaultsMode di sistema.

  • A livello globale, tramite la variabile di AWS_DEFAULTS_MODE ambiente.

Nota

Per qualsiasi modalità diversalegacy, i valori predefiniti forniti potrebbero cambiare man mano che le migliori pratiche si evolvono. Pertanto, se utilizzi una modalità diversa dalegacy, ti consigliamo di eseguire dei test durante l'aggiornamento di. SDK

Le impostazioni predefinite di Smart nella AWS SDKsand Tools Reference Guide fornisce un elenco delle proprietà di configurazione e dei relativi valori predefiniti nelle diverse modalità predefinite.

Scegliete il valore della modalità predefinita in base alle caratteristiche dell'applicazione e al tipo con AWS servizio cui l'applicazione interagisce.

Questi valori sono configurati tenendo conto di un'ampia gamma di AWS servizi opzioni. Per una distribuzione tipica di DynamoDB in cui sia le tabelle che l'applicazione DynamoDB sono distribuite in un'unica regione, la modalità defaults è la più rilevante tra in-region le modalità predefinite. standard

Esempio Configurazione del client SDK DynamoDB ottimizzata per chiamate a bassa latenza

L'esempio seguente regola i timeout su valori inferiori per una chiamata DynamoDB a bassa latenza prevista.

DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.builder() .defaultsMode(DefaultsMode.IN_REGION) .httpClientBuilder(AwsCrtAsyncHttpClient.builder()) .overrideConfiguration(ClientOverrideConfiguration.builder() .apiCallTimeout(Duration.ofSeconds(3)) .apiCallAttemptTimeout(Duration.ofMillis(500)) .build()) .build();

L'implementazione individuale del HTTP client può fornirti un controllo ancora più granulare sul timeout e sul comportamento di utilizzo della connessione. Ad esempio, per il client AWS CRT basato, è possibile abilitareConnectionHealthConfiguration, che consente al client di monitorare attivamente lo stato delle connessioni utilizzate. Per ulteriori informazioni, consulta Configurazione avanzata dei HTTP client AWS CRT basati nella Guida per gli AWS SDK for Java 2.x sviluppatori.

Configurazione Keep-Alive

L'abilitazione di keep-alive può ridurre le latenze riutilizzando le connessioni. Esistono due diversi tipi di keep-alive: Keep-Alive e Keep-Alive. HTTP TCP

  • HTTPKeep-Alive tenta di mantenere la HTTPS connessione tra il client e il server in modo che le richieste successive possano riutilizzare tale connessione. In questo modo si evita la pesante autenticazione sulle richieste successiveHTTPS. HTTPKeep-Alive è abilitato di default su tutti i client.

  • TCPKeep-Alive richiede che il sistema operativo sottostante invii piccoli pacchetti tramite la connessione socket per garantire ulteriormente che il socket sia mantenuto attivo e per rilevare immediatamente eventuali cadute. Ciò garantisce che una richiesta successiva non perda tempo a cercare di utilizzare un socket caduto. Per impostazione predefinita, TCP Keep-Alive è disabilitato su tutti i client. I seguenti esempi di codice mostrano come abilitarlo su ogni HTTP client. Se abilitato per tutti i HTTP client non CRT basati, l'effettivo meccanismo Keep-Alive dipende dal sistema operativo. Pertanto, è necessario configurare valori TCP Keep-Alive aggiuntivi, come il timeout e il numero di pacchetti, tramite il sistema operativo. Puoi farlo usando sysctl Linux o macOS o usando i valori di registro su Windows.

Esempio per abilitare TCP Keep-Alive su un client basato su Apache HTTP
DynamoDbClient client = DynamoDbClient.builder() .httpClientBuilder(ApacheHttpClient.builder().tcpKeepAlive(true)) .build();
URLConnectionHTTPclient basato

Qualsiasi client sincrono che utilizza il HTTP client URLConnection basato HttpURLConnectionnon dispone di un meccanismo per abilitare keep-alive.

Esempio per abilitare TCP Keep-Alive su un client basato su Netty HTTP
DynamoDbAsyncClient client = DynamoDbAsyncClient.builder() .httpClientBuilder(NettyNioAsyncHttpClient.builder().tcpKeepAlive(true)) .build();
Esempio per abilitare TCP Keep-Alive su un client basato AWS CRT HTTP

Con il HTTP client AWS CRT basato, puoi abilitare TCP keep-alive e controllarne la durata.

DynamoDbClient client = DynamoDbClient.builder() .httpClientBuilder(AwsCrtHttpClient.builder() .tcpKeepAliveConfiguration(TcpKeepAliveConfiguration.builder() .keepAliveInterval(Duration.ofSeconds(50)) .keepAliveTimeout(Duration.ofSeconds(5)) .build())) .build();

Quando si utilizza il client DynamoDB asincrono, è possibile TCP abilitare Keep-Alive come mostrato nel codice seguente.

DynamoDbAsyncClient client = DynamoDbAsyncClient.builder() .httpClientBuilder(AwsCrtAsyncHttpClient.builder() .tcpKeepAliveConfiguration(TcpKeepAliveConfiguration.builder() .keepAliveInterval(Duration.ofSeconds(50)) .keepAliveTimeout(Duration.ofSeconds(5)) .build())) .build();

Gestione degli errori

Per quanto riguarda la gestione delle eccezioni, utilizza eccezioni di runtime (non selezionate). AWS SDK for Java 2.x

L'eccezione di base, che copre tutte le SDK eccezioni, è SdkServiceException, che si estende da Java deselezionata. RuntimeException Se lo catturi, catturerai tutte le eccezioni che SDK genera.

SdkServiceExceptionha una sottoclasse chiamata. AwsServiceException Questa sottoclasse indica qualsiasi problema di comunicazione con. AWS servizio Ha una sottoclasse chiamata DynamoDbException, che indica un problema nella comunicazione con DynamoDB. Se lo rilevi, catturerai tutte le eccezioni relative a DynamoDB, ma nessun'altra eccezione. SDK

Sono disponibili tipi di eccezioni più specifici in. DynamoDbException Alcuni di questi tipi di eccezioni si applicano a operazioni sul piano di controllo come. TableAlreadyExistsException Altri si applicano alle operazioni sul piano dati. Di seguito è riportato un esempio di eccezione comune relativa al piano dati:

  • ConditionalCheckFailedException— Hai specificato una condizione nella richiesta che è risultata falsa. Ad esempio, è possibile che abbia provato un aggiornamento condizionale su un item, ma il valore effettivo dell'attributo non corrispondeva al valore previsto nella condizione. Una richiesta che fallisce in questo modo non viene ritentata.

In altre situazioni non è definita un'eccezione specifica. Ad esempio, quando le richieste vengono limitate, ProvisionedThroughputExceededException potrebbero essere generate quelle specifiche, mentre in altri casi viene generata una richiesta più genericaDynamoDbException. In entrambi i casi, puoi determinare se la limitazione ha causato l'eccezione controllando se restituisce. isThrottlingException() true

A seconda delle esigenze dell'applicazione, è possibile catturare tutte le AwsServiceException DynamoDbException istanze. Tuttavia, spesso è necessario un comportamento diverso in situazioni diverse. La logica utilizzata per gestire un errore nel controllo delle condizioni è diversa da quella per gestire il throttling. Definisci quali percorsi eccezionali vuoi affrontare e assicurati di testare i percorsi alternativi. Questo ti aiuta ad assicurarti di poter affrontare tutti gli scenari pertinenti.

Per un elenco degli errori più comuni che potresti riscontrare, consultaGestione degli errori con DynamoDB. Vedi anche Errori comuni in Amazon DynamoDB Reference API. Il API riferimento fornisce anche gli errori esatti possibili per ogni API operazione, ad esempio per l'Queryoperazione. Per informazioni sulla gestione delle eccezioni, consulta la sezione Gestione delle eccezioni AWS SDK for Java 2.x nella Guida per gli AWS SDK for Java 2.x sviluppatori.

AWS ID della richiesta

Ogni richiesta include un ID della richiesta, che può essere utile da recuperare se stai lavorando AWS Support per diagnosticare un problema. Ogni eccezione derivata da SdkServiceException ha un requestId()metodo disponibile per recuperare l'ID della richiesta.

Registrazione

L'utilizzo della registrazione SDK fornita può essere utile sia per catturare messaggi importanti dalle librerie client sia per scopi di debug più approfonditi. I logger sono gerarchici e vengono utilizzati come logger root. SDK software.amazon.awssdk È possibile configurare il livello con uno dei seguentiTRACE,,,DEBUG, INFOWARN, ERROR o. ALL OFF Il livello configurato si applica a quel logger e scende nella gerarchia dei logger.

Per la sua registrazione, AWS SDK for Java 2.x utilizza Simple Logging Façade for Java (). SLF4J Questo funge da livello di astrazione rispetto agli altri logger e puoi usarlo per collegare il logger che preferisci. Per istruzioni su come collegare i logger, consultate il manuale utente. SLF4J

Ogni logger ha un comportamento particolare. Per impostazione predefinita, il logger Log4j 2.x crea unConsoleAppender, che aggiunge gli eventi di registro System.out e i valori predefiniti al livello di registro. ERROR

Il SimpleLogger logger incluso negli SLF4J output per impostazione predefinita è e il valore predefinito è il livello di registro. System.err INFO

Ti consigliamo di impostare il livello in modo che qualsiasi implementazione WARN di software.amazon.awssdk produzione catturi eventuali messaggi importanti dalle librerie client SDK della piattaforma, limitando al contempo la quantità di output.

Se non SLF4J riesci a trovare un logger supportato nel percorso della classe (nessun SLF4J binding), l'impostazione predefinita è un'implementazione senza operazioni. Questa implementazione comporta la registrazione di messaggi che System.err spiegano che non è stato SLF4J possibile trovare un'implementazione del logger nel classpath. Per evitare questa situazione, è necessario aggiungere un'implementazione del logger. Per fare ciò, puoi aggiungere una dipendenza in Apache Maven pom.xml da artefatti, come o. org.slf4j.slf4j-simple org.apache.logging.log4j.log4j-slf4j2-imp

Per informazioni su come configurare la registrazione inSDK, inclusa l'aggiunta di dipendenze di registrazione alla configurazione dell'applicazione, consulta Logging with the for Java 2.x nella Developer Guide. SDK AWS SDK for Java

La seguente configurazione nel Log4j2.xml file mostra come regolare il comportamento di registrazione se si utilizza il logger Apache Log4j 2. Questa configurazione imposta il livello del logger root su. WARN Tutti i logger della gerarchia ereditano questo livello di registro, incluso il logger. software.amazon.awssdk

Per impostazione predefinita, l'output va a. System.out Nell'esempio seguente, sovrascriviamo ancora l'appender Log4j di output predefinito per applicare un Log4j personalizzato. PatternLayout

Log4j2.xmlEsempio di file di configurazione

La seguente configurazione registra i messaggi sulla console ai WARN livelli ERROR e per tutte le gerarchie di logger.

<Configuration status="WARN"> <Appenders> <Console name="ConsoleAppender" target="SYSTEM_OUT"> <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" /> </Console> </Appenders> <Loggers> <Root level="WARN"> <AppenderRef ref="ConsoleAppender"/> </Root> </Loggers> </Configuration>

AWS richiedere la registrazione degli ID

Quando qualcosa va storto, puoi trovare la richiesta IDs tra le eccezioni. Tuttavia, se desideri la richiesta IDs per le richieste che non generano eccezioni, puoi utilizzare la registrazione.

Il software.amazon.awssdk.request logger emette la richiesta IDs a livello. DEBUG L'esempio seguente estende il precedente configuration example per mantenere il livello del logger root al livelloERROR, al livello software.amazon.awssdk WARN at e al software.amazon.awssdk.request livello. DEBUG L'impostazione di questi livelli aiuta a catturare la richiesta IDs e altri dettagli relativi alla richiesta, come l'endpoint e il codice di stato.

<Configuration status="WARN"> <Appenders> <Console name="ConsoleAppender" target="SYSTEM_OUT"> <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" /> </Console> </Appenders> <Loggers> <Root level="ERROR"> <AppenderRef ref="ConsoleAppender"/> </Root> <Logger name="software.amazon.awssdk" level="WARN" /> <Logger name="software.amazon.awssdk.request" level="DEBUG" /> </Loggers> </Configuration>

Di seguito è riportato un esempio di output del log:

2022-09-23 16:02:08 [main] DEBUG software.amazon.awssdk.request:85 - Sending Request: DefaultSdkHttpFullRequest(httpMethod=POST, protocol=https, host=dynamodb.us-east-1.amazonaws.com, encodedPath=/, headers=[amz-sdk-invocation-id, Content-Length, Content-Type, User-Agent, X-Amz-Target], queryParameters=[]) 2022-09-23 16:02:08 [main] DEBUG software.amazon.awssdk.request:85 - Received successful response: 200, Request ID: QS9DUMME2NHEDH8TGT9N5V53OJVV4KQNSO5AEMVJF66Q9ASUAAJG, Extended Request ID: not available

Paginazione

Alcune richieste, come Queryand Scan, limitano la dimensione dei dati restituiti su una singola richiesta e richiedono l'esecuzione di richieste ripetute per richiamare le pagine successive.

È possibile controllare il numero massimo di elementi da leggere per ogni pagina con il Limit parametro. Ad esempio, è possibile utilizzare il Limit parametro per recuperare solo gli ultimi 10 elementi. Questo limite specifica quanti elementi leggere dalla tabella prima di applicare qualsiasi filtro. Se desideri esattamente 10 elementi dopo il filtraggio, non c'è modo di specificarlo. Puoi controllare solo il conteggio prefiltrato e controllare lato client quando hai effettivamente recuperato 10 articoli. Indipendentemente dal limite, le risposte hanno sempre una dimensione massima di 1 MB.

Un LastEvaluatedKey potrebbe essere incluso nella API risposta. Ciò indica che la risposta è terminata perché ha raggiunto un limite di conteggio o di dimensione. Questa chiave è l'ultima chiave valutata per quella risposta. Interagendo direttamente conAPI, è possibile recuperarla LastEvaluatedKey e passarla a una chiamata successiva per leggere il blocco successivo ExclusiveStartKey da quel punto di partenza. Se LastEvaluatedKey viene restituito no, significa che non ci sono più elementi che corrispondono alla chiamata or. Query Scan API

L'esempio seguente utilizza l'interfaccia di basso livello per limitare gli elementi a 100 in base al keyConditionExpression parametro.

QueryRequest.Builder queryRequestBuilder = QueryRequest.builder() .expressionAttributeValues(Map.of( ":pk_val", AttributeValue.fromS("123"), ":sk_val", AttributeValue.fromN("1000"))) .keyConditionExpression("pk = :pk_val AND sk > :sk_val") .limit(100) .tableName(TABLE_NAME); while (true) { QueryResponse queryResponse = DYNAMODB_CLIENT.query(queryRequestBuilder.build()); queryResponse.items().forEach(item -> { LOGGER.info("item PK: [" + item.get("pk") + "] and SK: [" + item.get("sk") + "]"); }); if (!queryResponse.hasLastEvaluatedKey()) { break; } queryRequestBuilder.exclusiveStartKey(queryResponse.lastEvaluatedKey()); }

AWS SDK for Java 2.x Possono semplificare questa interazione con DynamoDB fornendo metodi di impaginazione automatica che effettuano più chiamate di servizio per ottenere automaticamente le pagine successive di risultati. Ciò semplifica il codice, ma toglie il controllo sull'utilizzo delle risorse, che sarebbe possibile mantenere leggendo manualmente le pagine.

Utilizzando i Iterable metodi disponibili nel client DynamoDB, QueryPaginatorcome ScanPaginatore, si occupa SDK dell'impaginazione. Il tipo restituito da questi metodi è un iterabile personalizzato che è possibile utilizzare per scorrere tutte le pagine. Gestisce SDK internamente le chiamate di servizio per te. Utilizzando Java StreamAPI, è possibile gestire il risultato di QueryPaginator come illustrato nell'esempio seguente.

QueryPublisher queryPublisher = DYNAMODB_CLIENT.queryPaginator(QueryRequest.builder() .expressionAttributeValues(Map.of( ":pk_val", AttributeValue.fromS("123"), ":sk_val", AttributeValue.fromN("1000"))) .keyConditionExpression("pk = :pk_val AND sk > :sk_val") .limit(100) .tableName("YourTableName") .build()); queryPublisher.items().subscribe(item -> System.out.println(item.get("itemData"))).join();

Annotazioni delle classi di dati

Java SDK fornisce diverse annotazioni che puoi inserire negli attributi della tua classe di dati. Queste annotazioni influenzano il modo in cui SDK interagisce con gli attributi. Aggiungendo un'annotazione, puoi fare in modo che un attributo si comporti come un contatore atomico implicito, mantenga un valore di timestamp generato automaticamente o tenga traccia del numero di versione di un elemento. Per ulteriori informazioni, consulta Annotazioni della classe Data.