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à.
Riprova in AWS SDK per Kotlin
Chiamate per restituire occasionalmente eccezioni Servizi AWS impreviste. Alcuni tipi di errori, come gli errori di limitazione o gli errori transitori, potrebbero avere esito positivo se la chiamata viene ritentata.
Questa pagina descrive come il sistema AWS SDK per Kotlin gestisce automaticamente i nuovi tentativi e come personalizzare il comportamento dei tentativi per le applicazioni.
Comprensione del comportamento dei nuovi tentativi
Le seguenti sezioni spiegano in che modo l'SDK determina quando riprovare le richieste e quali eccezioni sono considerate riutilizzabili.
Configurazione predefinita per i nuovi tentativi
Per impostazione predefinita, ogni client di servizio viene configurato automaticamente con una strategia di ripetizione dei tentativi standard. La configurazione predefinita tenta una chiamata che fallisce fino a tre volte (il tentativo iniziale più due tentativi). Il ritardo che intercorre tra ogni chiamata è configurato con un backoff esponenziale e un jitter casuale per evitare tempeste di tentativi. Questa configurazione funziona per la maggior parte dei casi d'uso, ma può non essere adatta in alcune circostanze, ad esempio nei sistemi ad alta velocità.
L'SDK tenta di riprovare solo in caso di errori ripetibili. Esempi di errori riutilizzabili sono i timeout dei socket, la limitazione sul lato del servizio, gli errori di blocco simultanei o ottimistici e gli errori temporanei del servizio. I parametri mancanti o non validi, gli errori e le eccezioni di configurazione errata non sono considerati riutilizzabili. authentication/security
È possibile personalizzare la strategia di ripetizione standard impostando il numero massimo di tentativi, ritardi e backoff e la configurazione del token bucket.
Quali eccezioni sono riutilizzabili?
AWS SDK per Kotlin Utilizza una politica di ripetizione dei tentativi preconfigurata che determina quali eccezioni possono essere riprovate. La configurazione del client di servizio ha una retryPolicy
proprietà che specifica la politica applicata ai nuovi tentativi. Se non viene specificato alcun valore personalizzato, il valore predefinito è. AwsRetryPolicy
Le seguenti eccezioni sono ritenute riutilizzabili da: AwsRetryPolicy
Riutilizzabile tramite codice di errore
Qualsiasi ServiceException
con uno dei seguentisdkErrorMetadata.errorCode
:
BandwidthLimitExceeded
EC2ThrottledException
IDPCommunicationError
LimitExceededException
PriorRequestNotComplete
ProvisionedThroughputExceededException
RequestLimitExceeded
RequestThrottled
RequestThrottledException
RequestTimeout
RequestTimeoutException
SlowDown
ThrottledException
Throttling
ThrottlingException
TooManyRequestsException
TransactionInProgressException
Riutilizzabile tramite codice di stato HTTP
Qualsiasi ServiceException
con uno dei seguentisdkErrorMetadata.statusCode
:
500 (errore interno del servizio)
502 (gateway non valido)
503 (servizio non disponibile)
504 (timeout del gateway)
Riprovabile per tipo di errore
Qualsiasi ServiceException
con uno dei seguentisdkErrorMetadata.errorType
:
ErrorType.Server
(ad esempio errori interni del servizio)ErrorType.Client
(ad esempio una richiesta non valida, una risorsa non trovata, accesso negato, ecc.)
Riprovabile tramite metadati SDK
SdkBaseException
Ovunque:
sdkErrorMetadata.isRetryable
ètrue
(ad esempio un timeout sul lato client, un networking/socket errore, ecc.)sdkErrorMetadata.isThrottling
ètrue
(ad esempio fare troppe richieste in un breve lasso di tempo)
Per un elenco completo delle eccezioni che possono essere generate da ciascun client del servizio, consulta la documentazione di riferimento sull'API specifica del servizio.
Verifica se un'eccezione è riutilizzabile
Per determinare se l'SDK considera un'eccezione riprovevole, controlla la proprietà sulle eccezioni rilevate: isRetryable
try { dynamoDbClient.putItem { tableName = "MyTable" item = mapOf("id" to AttributeValue.S("123")) } } catch (e: SdkBaseException) { println("Exception occurred: ${e.message}") if (e.sdkErrorMetadata.isRetryable) { println("This exception is retryable - SDK will automatically retry") println("If you're seeing this, retries may have been exhausted") } else { println("This exception is not retryable - fix the underlying issue") // Common non-retryable scenarios. when { e.message?.contains("ValidationException") == true -> println("Check your request parameters") e.message?.contains("AccessDenied") == true -> println("Check your IAM permissions") e.message?.contains("ResourceNotFound") == true -> println("Verify the resource exists") } } }
Quali eccezioni raggiungono il codice quando i nuovi tentativi falliscono
Quando il meccanismo di riprova dell'SDK non è in grado di risolvere un problema, vengono generate eccezioni al codice dell'applicazione. La comprensione di questi tipi di eccezioni consente di implementare una gestione degli errori appropriata. Queste non sono le eccezioni che attivano i recuperi, ma vengono gestite internamente dall'SDK.
Il codice rileverà i seguenti tipi di eccezioni quando i nuovi tentativi sono esauriti o disabilitati:
- Eccezioni di servizio dopo l'esaurimento dei nuovi tentativi
-
Quando tutti i tentativi di nuovo tentativo falliscono, il codice rileva l'eccezione di servizio finale (sottoclasse di
AwsServiceException
) che ha causato il fallimento dell'ultimo tentativo. Potrebbe trattarsi di un errore di limitazione, di un errore del server o di un'altra eccezione specifica del servizio che l'SDK non è riuscito a risolvere mediante nuovi tentativi. - Eccezioni di rete dopo l'esaurimento dei tentativi
-
Se i problemi di rete persistono dopo tutti i tentativi di ripetizione, il codice rileva le
ClientException
istanze relative a problemi quali timeout di connessione, errori di risoluzione DNS e altri problemi di connettività che l'SDK non è riuscito a risolvere.
Utilizzate lo schema seguente per gestire queste eccezioni nella vostra applicazione:
try { s3Client.getObject { bucket = "amzn-s3-demo-bucket" key = "my-key" } } catch (e: AwsServiceException) { // Service-side errors that persisted through all retries. println("Service error after retries: ${e.errorDetails?.errorCode} - ${e.message}") // Handle specific service errors that couldn't be resolved. if (e.errorDetails?.errorCode == "ServiceQuotaExceededException" || e.errorDetails?.errorCode == "ThrottlingException") { println("Rate limiting persisted - consider longer delays or quota increase") } } catch (e: ClientException) { // Client-side errors (persistent network issues, DNS resolution failures, etc.) println("Client error after retries: ${e.message}") }
Personalizzazione del comportamento dei tentativi
Le sezioni seguenti mostrano come personalizzare il comportamento di riprova dell'SDK per il tuo caso d'uso specifico.
Configura il numero massimo di tentativi
È possibile personalizzare il numero massimo di tentativi predefiniti (3) nel blocco retryStrategy
DSL durante la creazione del client.
val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { maxAttempts = 5 } }
Con il client di servizio DynamoDB mostrato nello snippet precedente, l'SDK prova le chiamate API che falliscono fino a cinque volte (il tentativo iniziale più quattro tentativi).
È possibile disabilitare completamente i tentativi automatici impostando il numero massimo di tentativi su uno, come mostrato nel seguente frammento.
val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { maxAttempts = 1 // The SDK makes no retries. } }
Configura ritardi e backoff
Se è necessario un nuovo tentativo, la strategia di riprova predefinita attende prima di effettuare il tentativo successivo. Il ritardo per il primo tentativo è piccolo, ma aumenta esponenzialmente per i tentativi successivi. La quantità massima di ritardo è limitata in modo che non diventi troppo grande.
Infine, viene applicato un jitter casuale ai ritardi tra tutti i tentativi. Il jitter aiuta a mitigare l'effetto delle flotte di grandi dimensioni che possono causare tempeste di nuovi tentativi. (Vedi questo post del blog di AWS architettura
I parametri di ritardo sono configurabili nel blocco DSL. delayProvider
val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { delayProvider { initialDelay = 100.milliseconds maxBackoff = 5.seconds } } }
Con la configurazione mostrata nello snippet precedente, il client ritarda il primo tentativo fino a 100 millisecondi. Il tempo massimo tra un tentativo e l'altro è di 5 secondi.
I seguenti parametri sono disponibili per la regolazione dei ritardi e del backoff.
Parametro | Valore predefinito | Descrizione |
---|---|---|
initialDelay |
10 millisecondi | Il ritardo massimo per il primo tentativo. Quando viene applicato il jitter, il ritardo effettivo può essere inferiore. |
jitter |
1.0 (jitter completo) |
L'ampiezza massima con cui ridurre in modo casuale il ritardo calcolato. Il valore predefinito di 1,0 indica che il ritardo calcolato può essere ridotto a qualsiasi importo fino al 100% (ad esempio, fino a 0). Un valore pari a 0,5 indica che il ritardo calcolato può essere ridotto fino alla metà. Pertanto, un ritardo massimo di 10 ms potrebbe essere ridotto a un valore compreso tra 5 ms e 10 ms. Un valore pari a 0,0 significa che non viene applicato alcun jitter. Importante️ La configurazione Jitter è una funzionalità avanzata. La personalizzazione di questo comportamento non è normalmente consigliata. |
maxBackoff |
20 secondi | Il limite massimo di ritardo da applicare a qualsiasi tentativo. L'impostazione di questo valore limita la crescita esponenziale che si verifica tra i tentativi successivi e impedisce che il massimo calcolato sia troppo grande. Questo parametro limita il ritardo calcolato prima dell'applicazione del jitter. Se applicato, il jitter potrebbe ridurre ulteriormente il ritardo. |
scaleFactor |
1.5 | La base esponenziale in base alla quale verranno aumentati i ritardi massimi successivi. Ad esempio, con un valore
|
Configura il bucket retry token
È possibile modificare ulteriormente il comportamento della strategia di ripetizione standard regolando la configurazione predefinita del token bucket. Il retry token bucket aiuta a ridurre i tentativi che hanno meno probabilità di successo o che potrebbero richiedere più tempo per essere risolti, come i timeout e gli errori di throttling.
Importante
La configurazione del token bucket è una funzionalità avanzata. La personalizzazione di questo comportamento non è normalmente consigliata.
Ogni nuovo tentativo (incluso facoltativamente il tentativo iniziale) riduce una parte della capacità del bucket di token. L'importo diminuito dipende dal tipo di tentativo. Ad esempio, riprovare gli errori temporanei potrebbe essere conveniente, ma riprovare gli errori di timeout o di throttling potrebbe essere più costoso.
Un tentativo riuscito restituisce la capacità al bucket. Il bucket non può essere incrementato oltre la sua capacità massima né ridotto al di sotto dello zero.
A seconda del valore dell'useCircuitBreakerMode
impostazione, i tentativi di ridurre la capacità al di sotto dello zero producono uno dei seguenti risultati:
-
Se l'impostazione è TRUE, viene generata un'eccezione, ad esempio se sono stati effettuati troppi tentativi ed è improbabile che altri tentativi abbiano successo.
-
Se l'impostazione è FALSE, si verifica un ritardo, ad esempio, finché il bucket non raggiunge nuovamente una capacità sufficiente.
Nota
Quando l'interruttore si attiva (il token bucket raggiunge la capacità zero), l'SDK genera un messaggio ClientException
con il messaggio «Riprova la capacità superata». Si tratta di un'eccezione sul lato client, non di un'eccezioneAwsServiceException
, perché deriva dalla logica di riprova dell'SDK anziché dal servizio. AWS L'eccezione viene generata immediatamente senza tentare l'operazione, contribuendo a prevenire tempeste di tentativi durante le interruzioni del servizio.
I parametri del token bucket sono configurabili nel blocco DSL: tokenBucket
val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { tokenBucket { maxCapacity = 100 refillUnitsPerSecond = 2 } } }
I seguenti parametri sono disponibili per l'ottimizzazione del bucket del token retry:
Parametro | Valore predefinito | Descrizione |
---|---|---|
initialTryCost |
0 | L'importo da diminuire dal bucket per i tentativi iniziali. Il valore predefinito 0 indica che nessuna capacità verrà diminuita e quindi i tentativi iniziali non verranno interrotti o ritardati. |
initialTrySuccessIncrement |
1 | L'importo necessario per incrementare la capacità quando il tentativo iniziale ha avuto successo. |
maxCapacity |
500 | La capacità massima del token bucket. Il numero di token disponibili non può superare questo numero. |
refillUnitsPerSecond |
0 | La quantità di capacità riaggiunta al bucket ogni secondo. Un valore pari a 0 indica che nessuna capacità viene aggiunta automaticamente. (Ad esempio, solo i tentativi riusciti determinano un incremento della capacità). Un valore pari a 0 deve useCircuitBreakerMode essere TRUE. |
retryCost |
5 | L'importo da diminuire dal bucket per un tentativo a seguito di un errore temporaneo. Lo stesso importo viene reincrementato nel bucket se il tentativo ha esito positivo. |
timeoutRetryCost |
10 | L'importo da diminuire dal bucket per un tentativo a seguito di un timeout o di un errore di limitazione. Lo stesso importo viene reincrementato nel bucket se il tentativo ha esito positivo. |
useCircuitBreakerMode |
TRUE | Determina il comportamento quando un tentativo di diminuire la capacità comporterebbe la riduzione della capacità del bucket al di sotto dello zero. Se impostato su TRUE, il token bucket genererà un'eccezione che indica che non esiste più capacità di riprovare. Se impostato su FALSE, il token bucket ritarderà il tentativo fino a quando non sarà stata ripristinata una capacità sufficiente. |
Per informazioni dettagliate sui tipi di eccezioni generati durante gli scenari di nuovi tentativi, incluse le eccezioni relative agli interruttori automatici, vedere. Quali eccezioni raggiungono il codice quando i nuovi tentativi falliscono
Configurare i tentativi adattivi
In alternativa alla strategia di ripetizione standard, la strategia adattiva di riprova è un approccio avanzato che mira alla frequenza di richiesta ideale per ridurre al minimo gli errori di limitazione.
Importante
Adaptive retry è una modalità di riprova avanzata. L'utilizzo di questa strategia di nuovi tentativi non è in genere consigliato.
I tentativi adattivi includono tutte le funzionalità dei tentativi standard. Aggiunge un limitatore di velocità sul lato client che misura la frequenza delle richieste limitate rispetto alle richieste non limitate. Inoltre limita il traffico per cercare di rimanere entro una larghezza di banda sicura, evitando idealmente errori di limitazione.
La tariffa si adatta in tempo reale alle mutevoli condizioni di servizio e ai modelli di traffico e potrebbe aumentare o diminuire di conseguenza la velocità di traffico. In modo critico, il limitatore di velocità potrebbe ritardare i tentativi iniziali in scenari di traffico intenso.
La strategia di ripetizione adattiva dei tentativi viene selezionata fornendo un parametro aggiuntivo al metodo. retryStrategy
I parametri del limitatore di velocità sono configurabili nel blocco DSL. rateLimiter
val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy(AdaptiveRetryStrategy) { maxAttempts = 10 rateLimiter { minFillRate = 1.0 smoothing = 0.75 } } }
Nota
La strategia di ripetizione adattiva presuppone che il client lavori su una singola risorsa (ad esempio, una tabella DynamoDB o un bucket Amazon S3).
Se si utilizza un singolo client per più risorse, le limitazioni o le interruzioni associate a una risorsa comportano un aumento della latenza e degli errori quando il client accede a tutte le altre risorse. Quando utilizzi la strategia di ripetizione adattiva, ti consigliamo di utilizzare un singolo client per ogni risorsa.