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à.
Consigli per i QLDB driver Amazon
Importante
Avviso di fine del supporto: i clienti esistenti potranno utilizzare Amazon QLDB fino alla fine del supporto il 31/07/2025. Per ulteriori dettagli, consulta Migrare un Amazon QLDB Ledger ad Amazon Aurora Postgre
Questa sezione descrive le migliori pratiche per configurare e utilizzare il QLDB driver Amazon per qualsiasi lingua supportata. Gli esempi di codice forniti sono specifici per Java.
Questi consigli si applicano alla maggior parte dei casi d'uso comuni, ma un'unica soluzione non è adatta a tutti. Utilizza i seguenti consigli come ritieni opportuno per la tua applicazione.
Argomenti
Configurazione dell'oggetto QldbDriver
L'QldbDriver
oggetto gestisce le connessioni al registro gestendo un pool di sessioni che vengono riutilizzate tra le transazioni. Una sessione rappresenta una singola connessione al registro. QLDBsupporta una transazione in esecuzione attiva per sessione.
Importante
Per le versioni precedenti dei driver, la funzionalità di pool delle sessioni è ancora presente nell'PooledQldbDriver
oggetto anzichéQldbDriver
. Se utilizzi una delle seguenti versioni, sostituisci le eventuali menzioni di QldbDriver
con PooledQldbDriver
per il resto di questo argomento.
Driver | Versione |
---|---|
Java | 1.1.0 o precedente |
.NET | 0.1.0-beta |
Node.js | 1.0.0-rc.1 o prima |
Python | 2.0.2 o prima |
L'PooledQldbDriver
oggetto è obsoleto nella versione più recente dei driver. Si consiglia di eseguire l'aggiornamento alla versione più recente e di convertire tutte le istanze di to. PooledQldbDriver
QldbDriver
Configura QldbDriver come oggetto globale
Per ottimizzare l'uso di driver e sessioni, assicuratevi che nell'istanza dell'applicazione esista solo un'istanza globale del driver. Ad esempio, in Java, potete utilizzare framework di iniezione delle dipendenze come SpringQldbDriver
@Singleton public QldbDriver qldbDriver (AWSCredentialsProvider credentialsProvider, @Named(LEDGER_NAME_CONFIG_PARAM) String ledgerName) { QldbSessionClientBuilder builder = QldbSessionClient.builder(); if (null != credentialsProvider) { builder.credentialsProvider(credentialsProvider); } return QldbDriver.builder() .ledger(ledgerName) .transactionRetryPolicy(RetryPolicy .builder() .maxRetries(3) .build()) .sessionClientBuilder(builder) .build(); }
Configura i tentativi di riprova
Il driver ritenta automaticamente le transazioni quando si verificano eccezioni transitorie comuni (come o). SocketTimeoutException
NoHttpResponseException
Per impostare il numero massimo di tentativi, è possibile utilizzare il maxRetries
parametro dell'oggetto di transactionRetryPolicy
configurazione durante la creazione di un'istanza di. QldbDriver
(Per le versioni precedenti dei driver elencate nella sezione precedente, utilizzate il retryLimit
parametro diPooledQldbDriver
.)
Il valore predefinito di maxRetries
è 4
.
Errori sul lato client, ad esempio l'InvalidParameterException
impossibilità di riprovare. Quando si verificano, la transazione viene interrotta, la sessione viene restituita al pool e l'eccezione viene generata al client del driver.
Configura il numero massimo di sessioni e transazioni simultanee
Il numero massimo di sessioni contabili utilizzate da un'istanza di QldbDriver
per eseguire transazioni è definito dal relativo maxConcurrentTransactions
parametro. (Per le versioni precedenti dei driver elencate nella sezione precedente, questo valore è definito dal poolLimit
parametro diPooledQldbDriver
.)
Questo limite deve essere maggiore di zero e minore o uguale al numero massimo di HTTP connessioni aperte consentite dal client di sessione, come definito dallo specifico AWS SDK. Ad esempio, in Java, il numero massimo di connessioni è impostato nell'ClientConfigurationoggetto.
Il valore predefinito di maxConcurrentTransactions
è l'impostazione di connessione massima del tuo AWS SDK.
Quando lo configuri QldbDriver
nella tua applicazione, prendi in considerazione le seguenti considerazioni sulla scalabilità:
-
Il pool deve avere sempre almeno lo stesso numero di sessioni quante sono le transazioni in esecuzione simultanea che si prevede di effettuare.
-
In un modello multithread in cui un thread supervisore delega ai thread di lavoro, il driver dovrebbe avere un numero di sessioni almeno pari al numero di thread di lavoro. Altrimenti, al picco di carico, i thread aspetteranno in fila una sessione disponibile.
-
Il limite di servizio delle sessioni attive simultanee per registro è definito in. Quote e limiti in Amazon QLDB Assicurati di non configurare più di questo limite di sessioni simultanee da utilizzare per un singolo registro tra tutti i client.
Riprovare con le eccezioni
Quando riprovi a risolvere le eccezioni che si verificano inQLDB, prendi in considerazione i seguenti consigli.
Riprovare OccConflictException
Le eccezioni al conflitto Optimistic Concurrency Control (OCC) si verificano quando i dati a cui accede la transazione sono cambiati dall'inizio della transazione. QLDBgenera questa eccezione durante il tentativo di confermare la transazione. Il driver ritenta la transazione fino a un numero massimo di volte pari a maxRetries
quello configurato.
Per ulteriori informazioni OCC e procedure consigliate per l'utilizzo degli indici per limitare i OCC conflitti, vedere. Modello di QLDB concorrenza Amazon
Riprovare con altre eccezioni diverse da QldbDriver
Per riprovare una transazione all'esterno del driver quando durante l'esecuzione vengono generate eccezioni personalizzate e definite dall'applicazione, è necessario eseguire il wrapping della transazione. Ad esempio, in Java, il codice seguente mostra come utilizzare la libreria Reslience4J
private final RetryConfig retryConfig = RetryConfig.custom() .maxAttempts(MAX_RETRIES) .intervalFunction(IntervalFunction.ofExponentialRandomBackoff()) // Retry this exception .retryExceptions(InvalidSessionException.class, MyRetryableException.class) // But fail for any other type of exception extended from RuntimeException .ignoreExceptions(RuntimeException.class) .build(); // Method callable by a client public void myTransactionWithRetries(Params params) { Retry retry = Retry.of("registerDriver", retryConfig); Function<Params, Void> transactionFunction = Retry.decorateFunction( retry, parameters -> transactionNoReturn(params)); transactionFunction.apply(params); } private Void transactionNoReturn(Params params) { try (driver.execute(txn -> { // Transaction code }); } return null; }
Nota
Riprovare una transazione al di fuori del driver ha un effetto moltiplicatoreQLDB. Ad esempio, se QldbDriver
è configurato per riprovare tre volte e anche la logica di ripetizione personalizzata riprova tre volte, la stessa transazione può essere ritentata fino a nove volte.
Rendere le transazioni idempotenti
È buona norma rendere le transazioni di scrittura idempotenti per evitare effetti collaterali imprevisti in caso di nuovi tentativi. Una transazione è idempotente se può essere eseguita più volte e produrre risultati identici ogni volta.
Per ulteriori informazioni, consulta Modello di QLDB concorrenza Amazon.
Ottimizzazione delle prestazioni
Per ottimizzare le prestazioni quando esegui transazioni utilizzando il driver, prendi le seguenti considerazioni:
-
L'
execute
operazione effettua sempre un minimo di treSendCommand
API chiamate aQLDB, inclusi i seguenti comandi:-
StartTransaction
-
ExecuteStatement
Questo comando viene richiamato per ogni istruzione PartiQL eseguita nel
execute
blocco. -
CommitTransaction
Considerate il numero totale di API chiamate effettuate quando calcolate il carico di lavoro complessivo dell'applicazione.
-
-
In generale, consigliamo di iniziare con uno scrittore a thread singolo e di ottimizzare le transazioni raggruppando più istruzioni all'interno di un'unica transazione. Massimizza le quote relative alle dimensioni delle transazioni, alle dimensioni dei documenti e al numero di documenti per transazione, come definito in. Quote e limiti in Amazon QLDB
-
Se il batching non è sufficiente per carichi di transazioni di grandi dimensioni, puoi provare il multithreading aggiungendo altri writer. Tuttavia, è necessario considerare attentamente i requisiti dell'applicazione per il sequenziamento di documenti e transazioni e la complessità aggiuntiva che ciò comporta.
Esecuzione di più rendiconti per transazione
Come descritto nella sezione precedente, è possibile eseguire più istruzioni per transazione per ottimizzare le prestazioni dell'applicazione. Nel seguente esempio di codice, si esegue una query su una tabella e quindi si aggiorna un documento in quella tabella all'interno di una transazione. A tale scopo, è necessario passare un'espressione lambda all'execute
operazione.
L'execute
operazione del driver avvia implicitamente una sessione e una transazione in quella sessione. Ogni istruzione eseguita nell'espressione lambda è inclusa nella transazione. Dopo l'esecuzione di tutte le istruzioni, il driver esegue automaticamente la transazione. Se un'istruzione ha esito negativo dopo l'esaurimento del limite di tentativi automatici, la transazione viene interrotta.
Propaga le eccezioni in una transazione
Quando si eseguono più rendiconti per transazione, in genere non consigliamo di catturare e ingoiare eccezioni all'interno della transazione.
Ad esempio, in Java, il seguente programma rileva qualsiasi istanza diRuntimeException
, registra l'errore e continua. Questo esempio di codice è considerato una pratica scorretta perché la transazione ha esito positivo anche quando l'UPDATE
istruzione ha esito negativo. Pertanto, il client potrebbe presumere che l'aggiornamento abbia avuto esito positivo quando non lo è stato.
avvertimento
Non utilizzare questo esempio di codice. Viene fornito per mostrare un esempio anti-pattern considerato una cattiva pratica.
// DO NOT USE this code example because it is considered bad practice
public static void main(final String... args) {
ConnectToLedger.getDriver().execute(txn -> {
final Result selectTableResult = txn.execute("SELECT * FROM Vehicle WHERE VIN ='123456789'");
// Catching an error inside the transaction is an anti-pattern because the operation might
// not succeed.
// In this example, the transaction succeeds even when the update statement fails.
// So, the client might assume that the update succeeded when it didn't.
try {
processResults(selectTableResult);
String model = // some code that extracts the model
final Result updateResult = txn.execute("UPDATE Vehicle SET model = ? WHERE VIN = '123456789'",
Constants.MAPPER.writeValueAsIonValue(model));
} catch (RuntimeException e) {
log.error("Exception when updating the Vehicle table {}", e.getMessage());
}
});
log.info("Vehicle table updated successfully.");
}
Propaga invece (ribolle up) l'eccezione. Se una parte della transazione fallisce, lascia che l'execute
operazione interrompa la transazione in modo che il client possa gestire l'eccezione di conseguenza.