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à.
Suggerimenti per i driver Amazon QLDB
Questa sezione descrive le best practice per la configurazione e l'utilizzo del driver Amazon QLDB per qualsiasi lingua supportata. Gli esempi di codice forniti sono specificamente per Java.
Questi consigli si applicano alla maggior parte dei casi d'uso tipici, ma la taglia unica non è adatta a tutti. Utilizza i seguenti consigli come preferisci per la tua applicazione.
Argomenti
Configurazione della QldbDriver oggetto
LaQldbDriver
object gestisce le connessioni al libro mastro mantenendo un pool disessioniche vengono riutilizzati tra le transazioni. UNsessionerappresenta una singola connessione con il libro contabile. QLDB supporta una transazione attiva per sessione.
Importante
Per le versioni precedenti del driver, la funzionalità di pooling delle sessioni è ancora presentePooledQldbDriver
l'oggetto anzichéQldbDriver
. Se si utilizza una delle seguenti versioni, sostituire qualsiasi menzione diQldbDriver
conPooledQldbDriver
per il resto di questo argomento.
Driver | Versione |
---|---|
Java | 1.1.0 o precedenti |
.NET | 0.1.0-beta |
Node.js | 1.0.0-rc.1 o precedenti |
Python | 2.0.2 o precedenti |
LaPooledQldbDriver
l'oggetto è obsoleto nella versione più recente dei driver. Ti consigliamo di eseguire l'aggiornamento alla versione più recente e convertire qualsiasi istanza diPooledQldbDriver
aQldbDriver
.
Configura QldbDriver come oggetto globale
Per ottimizzare l'uso di driver e sessioni, assicurarsi che nell'istanza dell'applicazione esista solo un'istanza globale del driver. Ad esempio, in Java, è possibile utilizzareiniezione dipendenzaFramework comePrimaveraQldbDriver
come singleton.
@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(); }
Configurare i tentativi di nuovo tentativo
Il conducente ritenta automaticamente le transazioni quando eccezioni transitorie comuni (come ad esempioSocketTimeoutException
oNoHttpResponseException
) si verificano. Per impostare il numero massimo di tentativi, è possibile utilizzare ilmaxRetries
parametro deltransactionRetryPolicy
oggetto di configurazione durante la creazione di un'istanza diQldbDriver
. (Per le versioni precedenti del driver elencate nella sezione precedente, utilizzare ilretryLimit
parametro diPooledQldbDriver
.)
Il valore predefinito di maxRetries
è 4
.
Errori lato client comeInvalidParameterException
non può essere riprovato. Quando si verificano, la transazione viene interrotta, la sessione viene restituita al pool e l'eccezione viene lanciata al client del conducente.
Configurare il numero massimo di sessioni e transazioni simultanee
Il numero massimo di sessioni contabili utilizzate da un'istanza diQldbDriver
per eseguire transazioni è definito dal suomaxConcurrentTransactions
Parametro . (Per le versioni precedenti del driver elencate nella sezione precedente, questo è definito dalpoolLimit
parametro diPooledQldbDriver
.)
Questo limite deve essere maggiore di zero e minore o uguale al numero massimo di connessioni HTTP aperte consentite dal client di sessione, come definito dallo specificoAWSSDK. Ad esempio, in Java, il numero massimo di connessioni è impostato nelClientConfigurationoggetto.
Il valore predefinito dimaxConcurrentTransactions
è l'impostazione massima di connessione del tuoAWSSDK.
Quando si configura ilQldbDriver
nella tua applicazione, prendi le seguenti considerazioni di scalabilità:
-
Il pool dovrebbe avere sempre almeno il numero di sessioni pari al numero di transazioni in esecuzione contemporanea che si prevede di avere.
-
In un modello multi-thread in cui un thread di supervisore delega ai thread di lavoro, il driver dovrebbe avere almeno il numero di sessioni del numero di thread di lavoro. Altrimenti, al picco di carico, i thread saranno in linea per una sessione disponibile.
-
Il limite di servizio delle sessioni attive simultanee per libro contabile è definito inQuote e limiti in Amazon QLDB. Assicurati di non configurare più di questo limite di sessioni simultanee da utilizzare per un singolo libro contabile in tutti i client.
Nuovi tentativi di eccezione
Quando si riprova le eccezioni che si verificano in QLDB, prendere in considerazione le seguenti raccomandazioni.
Nuovi tentativi su OCCConflictException
Controllo ottimistico della concorrenzaLe eccezioni di conflitto (OCC) si verificano quando i dati a cui si accede alla transazione sono cambiati dall'inizio della transazione. QLDB genera questa eccezione mentre si tenta di eseguire il commit della transazione. Il conducente ritira la transazione fino a quante voltemaxRetries
è configurato.
Per ulteriori informazioni sull'OCC e sulle best practice per l'utilizzo di indici per limitare i conflitti OCC, vedereModello di concorrenza Amazon QLDB.
Riprovare altre eccezioni al di fuori di QLDBDriver
Per riprovare una transazione al di fuori del driver quando personalizzate vengono generate eccezioni definite dall'applicazione durante il runtime, è necessario avvolgere la transazione. Ad esempio, in Java, il codice seguente mostra come utilizzare il codiceReslienza 4J
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
Il ritentativo di una transazione al di fuori del driver QLDB ha un effetto moltiplicatore. Ad esempio, seQldbDriver
è configurato per riprovare tre volte e anche la logica di riprova personalizzata torna tre volte, la stessa transazione può essere ripetuta fino a nove volte.
Rendere idempotenti le transazioni
Come best practice, rendi le tue transazioni di scrittura idempotenti per evitare effetti collaterali imprevisti in caso di tentativi. Una transazione è.idempotentese può essere eseguito più volte e produrre risultati identici ogni volta.
Per ulteriori informazioni, consulta Modello di concorrenza Amazon QLDB.
Ottimizzazione delle prestazioni
Per ottimizzare le prestazioni quando si eseguono transazioni utilizzando il driver, attenersi alle seguenti considerazioni:
-
La
execute
l'operazione fa sempre un minimo di treSendCommand
Chiamate API a QLDB, inclusi i seguenti comandi:-
StartTransaction
-
ExecuteStatement
Questo comando viene richiamato per ogni istruzione PartiQL eseguita nella
execute
blocco. -
CommitTransaction
Considera il numero totale di chiamate API effettuate quando si calcola il carico di lavoro complessivo dell'applicazione.
-
-
In generale, si consiglia di iniziare con uno scrittore a thread singolo e di ottimizzare le transazioni mediante il batch di più istruzioni all'interno di una singola transazione. Massimizzare le quote relative alle dimensioni della transazione, alla dimensione del documento e al numero di documenti per transazione, come definito nellaQuote e limiti in Amazon QLDB.
-
Se il batch non è sufficiente per carichi di transazioni di grandi dimensioni, puoi provare il multi-threading aggiungendo altri scrittori. Tuttavia, è necessario considerare attentamente i requisiti applicativi per il sequenziamento di documenti e transazioni e la complessità aggiuntiva che questo introduce.
Esecuzione di più rendiconti per
Come descritto nelsezione precedente, è possibile eseguire più rendiconti per transazione per ottimizzare le prestazioni dell'applicazione. Nell'esempio di codice seguente, si esegue una query su una tabella e quindi si aggiorna un documento in tale tabella all'interno di una transazione. Lo fai passando un'espressione lambda alexecute
operazione.
Il conducenteexecute
operazione avvia implicitamente una sessione e una transazione in quella sessione. Ogni istruzione eseguita nell'espressione lambda è racchiusa nella transazione. Dopo aver eseguito tutte le istruzioni, il conducente commette automaticamente la transazione. Se una dichiarazione non riesce dopo che il limite di tentativi automatici è stato esaurito, la transazione viene interrotta.
Propagare le eccezioni in una transazione
Quando si eseguono più rendiconti per transazione, generalmente non consigliamo di catch e ingoiare eccezioni all'interno della transazione.
Ad esempio, in Java, il seguente programma cattura qualsiasi istanza diRuntimeException
, registra l'errore e continua. Questo esempio di codice è considerato una cattiva pratica perché la transazione ha esito positivo anche quandoUPDATE
l'istruzione fallisce. Quindi, il client potrebbe presumere che l'aggiornamento abbia avuto esito positivo quando non è stato eseguito.
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 (ribalta) invece l'eccezione. Se una qualsiasi parte della transazione fallisce, lascia cheexecute
operazione interrompe la transazione in modo che il cliente possa gestire l'eccezione di conseguenza.