Réessaie dans AWS SDK pour Kotlin - AWS SDK pour Kotlin

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Réessaie dans AWS SDK pour Kotlin

Appels renvoyant de Services AWS temps en temps des exceptions inattendues. Certains types d'erreurs, tels que les erreurs de régulation ou les erreurs transitoires, peuvent réussir si l'appel est relancé.

Cette page décrit comment le gestionnaire AWS SDK pour Kotlin gère automatiquement les nouvelles tentatives et comment personnaliser le comportement des nouvelles tentatives pour vos applications.

Comprendre le comportement des nouvelles tentatives

Les sections suivantes expliquent comment le SDK détermine à quel moment les demandes doivent être réessayées et quelles exceptions sont considérées comme réessayables.

Configuration de nouvelle tentative par défaut

Par défaut, chaque client de service est automatiquement configuré avec une stratégie de nouvelle tentative standard. La configuration par défaut essaie un appel qui échoue jusqu'à trois fois (la première tentative plus deux tentatives). Le délai entre chaque appel est configuré avec un recul exponentiel et une instabilité aléatoire afin d'éviter les tempêtes de nouvelles tentatives. Cette configuration fonctionne dans la majorité des cas d'utilisation, mais peut s'avérer inappropriée dans certaines circonstances, comme dans le cas des systèmes à haut débit.

Le SDK tente de réessayer uniquement en cas d'erreur réessayable. Parmi les erreurs réessayables, citons les délais d'expiration des sockets, le ralentissement côté service, la simultanéité ou les échecs de verrouillage optimistes, ainsi que les erreurs de service transitoires. Les paramètres manquants ou non valides, les authentication/security erreurs et les exceptions de mauvaise configuration ne sont pas considérés comme réessayables.

Vous pouvez personnaliser la stratégie de réessai standard en définissant le nombre maximal de tentatives, de délais et d'interruptions, ainsi que la configuration du bucket de jetons.

Quelles exceptions sont réessayables ?

AWS SDK pour Kotlin Utilise une politique de nouvelle tentative préconfigurée qui détermine quelles exceptions peuvent être réessayées. La configuration du client de service possède une retryPolicy propriété qui spécifie la politique appliquée aux nouvelles tentatives. Si aucune valeur personnalisée n'est spécifiée, la valeur par défaut est AwsRetryPolicy.

Les exceptions suivantes sont considérées comme réessayables par : AwsRetryPolicy

Réessayable par code d'erreur

N'importe ServiceException lequel avec un sdkErrorMetadata.errorCode des éléments suivants :

  • BandwidthLimitExceeded

  • EC2ThrottledException

  • IDPCommunicationError

  • LimitExceededException

  • PriorRequestNotComplete

  • ProvisionedThroughputExceededException

  • RequestLimitExceeded

  • RequestThrottled

  • RequestThrottledException

  • RequestTimeout

  • RequestTimeoutException

  • SlowDown

  • ThrottledException

  • Throttling

  • ThrottlingException

  • TooManyRequestsException

  • TransactionInProgressException

Réessayable par code d'état HTTP

N'importe ServiceException lequel avec un sdkErrorMetadata.statusCode des éléments suivants :

  • 500 (erreur de service interne)

  • 502 (Mauvaise passerelle)

  • 503 (Service non disponible)

  • 504 (délai d'expiration de la passerelle)

Réessayable par type d'erreur

N'importe ServiceException lequel avec un sdkErrorMetadata.errorType des éléments suivants :

  • ErrorType.Server(telles que des erreurs de service internes)

  • ErrorType.Client(comme une demande non valide, une ressource introuvable, un accès refusé, etc.)

Réessayable à l'aide des métadonnées du SDK

N'importe SdkBaseException où :

  • sdkErrorMetadata.isRetryableest true (tel qu'un délai d'attente côté client, une networking/socket erreur, etc.)

  • sdkErrorMetadata.isThrottlingest true (par exemple, faire trop de demandes en peu de temps)

Pour obtenir la liste complète des exceptions pouvant être émises par chaque client de service, consultez la documentation de référence des API spécifiques au service.

Vérifiez si une exception est réessayable

Pour déterminer si le SDK considère qu'une exception peut être réessayée, vérifiez la isRetryable propriété des exceptions détectées :

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

Quelles exceptions atteignent votre code lorsque les nouvelles tentatives échouent

Lorsque le mécanisme de nouvelle tentative du SDK ne permet pas de résoudre un problème, des exceptions sont apportées au code de votre application. La compréhension de ces types d'exceptions vous permet de mettre en œuvre une gestion appropriée des erreurs. Ce ne sont pas ces exceptions qui déclenchent les récupérations : elles sont gérées en interne par le SDK.

Votre code détectera les types d'exceptions suivants lorsque les nouvelles tentatives seront épuisées ou désactivées :

Exceptions de service après l'épuisement des nouvelles tentatives

Lorsque toutes les tentatives échouent, votre code détecte la dernière exception de service (sous-classe deAwsServiceException) à l'origine de l'échec de la dernière tentative. Il peut s'agir d'une erreur de régulation, d'une erreur de serveur ou d'une autre exception spécifique au service que le SDK n'a pas pu résoudre par de nouvelles tentatives.

Exceptions réseau après épuisement des nouvelles tentatives

Lorsque les problèmes réseau persistent malgré toutes les tentatives, votre code détecte les ClientException instances pour détecter des problèmes tels que des délais de connexion, des échecs de résolution DNS ou d'autres problèmes de connectivité que le SDK n'a pas pu résoudre.

Utilisez le modèle suivant pour gérer ces exceptions dans votre application :

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

Personnalisation du comportement des nouvelles tentatives

Les sections suivantes montrent comment personnaliser le comportement de nouvelle tentative du SDK en fonction de votre cas d'utilisation spécifique.

Configurer le nombre maximal de tentatives

Vous pouvez personnaliser le nombre maximal de tentatives par défaut (3) dans le bloc retryStrategy DSL lors de la construction du client.

val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { maxAttempts = 5 } }

Avec le client de service DynamoDB illustré dans l'extrait précédent, le SDK essaie les appels d'API qui échouent jusqu'à cinq fois (la première tentative plus quatre nouvelles tentatives).

Vous pouvez désactiver complètement les tentatives automatiques en fixant le nombre maximum de tentatives à une, comme indiqué dans l'extrait suivant.

val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { maxAttempts = 1 // The SDK makes no retries. } }

Configurer les délais et les retards

Si une nouvelle tentative est nécessaire, la stratégie de nouvelle tentative par défaut attend avant d'effectuer la prochaine tentative. Le délai de la première tentative est faible, mais il augmente de façon exponentielle lors des tentatives ultérieures. Le délai maximal est plafonné afin qu'il ne devienne pas trop important.

Enfin, une instabilité aléatoire est appliquée aux délais entre toutes les tentatives. L'instabilité contribue à atténuer les effets des grandes flottes qui peuvent provoquer des tempêtes de nouvelles tentatives. (Consultez ce billet de blog sur AWS l'architecture pour une discussion plus approfondie sur le recul et l'instabilité exponentiels.)

Les paramètres de délai sont configurables dans le bloc delayProvider DSL.

val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { delayProvider { initialDelay = 100.milliseconds maxBackoff = 5.seconds } } }

Avec la configuration présentée dans l'extrait précédent, le client retarde la première tentative jusqu'à 100 millisecondes. Le délai maximum entre chaque nouvelle tentative est de 5 secondes.

Les paramètres suivants sont disponibles pour le réglage des délais et du ralentissement.

Paramètre Valeur par défaut Description
initialDelay 10 millisecondes Délai maximal pour la première tentative. Lorsque de la gigue est appliquée, le délai réel peut être moindre.
jitter 1,0 (gigue complète)

Amplitude maximale permettant de réduire de manière aléatoire le délai calculé. La valeur par défaut de 1,0 signifie que le délai calculé peut être réduit à n'importe quel montant jusqu'à 100 % (par exemple, jusqu'à 0). Une valeur de 0,5 signifie que le délai calculé peut être réduit de moitié au maximum. Ainsi, un délai maximum de 10 ms pourrait être réduit à une valeur comprise entre 5 ms et 10 ms. Une valeur de 0,0 signifie qu'aucune instabilité n'est appliquée.

Important

️ La configuration Jitter est une fonctionnalité avancée. La personnalisation de ce comportement n'est généralement pas recommandée.

maxBackoff 20 secondes Le délai maximal à appliquer à toute tentative. La définition de cette valeur limite la croissance exponentielle qui se produit entre les tentatives suivantes et évite que le maximum calculé ne soit trop élevé. Ce paramètre limite le délai calculé avant l'application de la gigue. Si elle est appliquée, la gigue peut encore réduire le délai.
scaleFactor 1.5

Base exponentielle selon laquelle les délais maximaux ultérieurs seront augmentés. Par exemple, étant donné un an initialDelay de 10 ms et un a scaleFactor de 1,5, les délais maximaux suivants seraient calculés :

  • Réessayer 1 : 10 ms × 1,5 = 10 ms

  • Réessai 2 : 10 ms × 1,5¹ = 15 ms

  • Réessai 3 : 10 ms × 1,5 ² = 22,5 ms

  • Réessai 4 : 10 ms × 1,5³ = 33,75 ms

Lorsque l'instabilité est appliquée, le montant réel de chaque retard peut être moindre.

Configurer le bucket de jetons Retry

Vous pouvez modifier davantage le comportement de la stratégie de nouvelle tentative standard en ajustant la configuration du bucket de jetons par défaut. Le bucket de jetons de nouvelle tentative permet de réduire le nombre de tentatives qui ont moins de chances de réussir ou dont la résolution peut prendre plus de temps, telles que les échecs liés au délai imparti ou à la limitation des délais.

Important

La configuration du bucket à jetons est une fonctionnalité avancée. La personnalisation de ce comportement n'est généralement pas recommandée.

Chaque nouvelle tentative (y compris éventuellement la tentative initiale) réduit une partie de la capacité du bucket de jetons. Le montant décrémenté dépend du type de tentative. Par exemple, il peut être peu coûteux de réessayer des erreurs transitoires, mais une nouvelle tentative d'expiration ou de limitation des erreurs peut s'avérer plus coûteuse.

Une tentative réussie rétablit la capacité du compartiment. Le godet ne doit pas être incrémenté au-delà de sa capacité maximale ni décrémenté en dessous de zéro.

En fonction de la valeur du useCircuitBreakerMode paramètre, les tentatives de réduction de la capacité en dessous de zéro entraînent l'un des résultats suivants :

  • Si le paramètre est VRAI, une exception est déclenchée. Par exemple, si trop de tentatives ont eu lieu et qu'il est peu probable que d'autres tentatives aboutissent.

  • Si le paramètre est FALSE, il y a un délai, par exemple, jusqu'à ce que le compartiment ait de nouveau une capacité suffisante.

Note

Lorsque le disjoncteur s'active (la capacité du compartiment à jetons atteint zéro), le SDK émet un message ClientException avec le message « Capacité de réessai dépassée ». Il s'agit d'une exception côté client, et non d'une exceptionAwsServiceException, car elle provient de la logique de nouvelle tentative du SDK plutôt que du service. AWS L'exception est déclenchée immédiatement sans tentative d'opération, ce qui permet d'éviter de nouvelles tentatives en cas de panne de service.

Les paramètres du bucket de jetons sont configurables dans le bloc tokenBucket DSL :

val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { tokenBucket { maxCapacity = 100 refillUnitsPerSecond = 2 } } }

Les paramètres suivants sont disponibles pour régler le bucket de jetons Retry :

Paramètre Valeur par défaut Description
initialTryCost 0 Le montant à déduire du bucket lors des premières tentatives. La valeur par défaut de 0 signifie qu'aucune capacité ne sera décrémentée et que les tentatives initiales ne seront donc ni interrompues ni retardées.
initialTrySuccessIncrement 1 Le montant à augmenter lorsque la première tentative a été couronnée de succès.
maxCapacity 500 Capacité maximale du bucket de jetons. Le nombre de jetons disponibles ne peut pas dépasser ce nombre.
refillUnitsPerSecond 0 Quantité de capacité ajoutée à nouveau au godet chaque seconde. Une valeur de 0 signifie qu'aucune capacité n'est automatiquement ajoutée à nouveau. (Par exemple, seules les tentatives réussies permettent d'augmenter la capacité). Une valeur de 0 useCircuitBreakerMode doit être vraie.
retryCost 5 Le montant à déduire du compartiment en cas de tentative consécutive à un échec temporaire. Le même montant est réincrémenté dans le compartiment si la tentative est réussie.
timeoutRetryCost 10 Le montant à déduire du compartiment en cas de tentative consécutive à un délai d'expiration ou à une défaillance de la régulation. Le même montant est réincrémenté dans le compartiment si la tentative est réussie.
useCircuitBreakerMode TRUE Détermine le comportement lorsqu'une tentative de réduction de la capacité entraîne une chute de la capacité du compartiment en dessous de zéro. Lorsque la valeur est TRUE, le bucket de jetons génère une exception indiquant qu'il n'existe plus de capacité de nouvelle tentative. Lorsque la valeur est FALSE, le bucket de jetons retarde la tentative jusqu'à ce que la capacité soit suffisante.

Pour des informations détaillées sur les types d'exceptions déclenchés lors de scénarios de nouvelle tentative, y compris les exceptions relatives aux disjoncteurs, consultezQuelles exceptions atteignent votre code lorsque les nouvelles tentatives échouent.

Configuration de nouvelles tentatives adaptatives

Comme alternative à la stratégie de nouvelle tentative standard, la stratégie de nouvelle tentative adaptative est une approche avancée qui recherche le taux de demandes idéal afin de minimiser les erreurs de limitation.

Important

Les tentatives adaptatives sont un mode de nouvelle tentative avancé. L'utilisation de cette stratégie de nouvelle tentative n'est généralement pas recommandée.

Les tentatives adaptatives incluent toutes les fonctionnalités des tentatives standard. Il ajoute un limiteur de débit côté client qui mesure le taux de demandes limitées par rapport aux demandes non limitées. Cela limite également le trafic pour tenter de rester dans une bande passante sûre, ce qui ne provoque idéalement aucune erreur de régulation.

Le tarif s'adapte en temps réel à l'évolution des conditions de service et des modèles de trafic et peut augmenter ou diminuer le taux de trafic en conséquence. Surtout, le limiteur de débit peut retarder les premières tentatives dans les scénarios à fort trafic.

Vous sélectionnez la stratégie de nouvelle tentative adaptative en fournissant un paramètre supplémentaire à la retryStrategy méthode. Les paramètres du limiteur de débit sont configurables dans le bloc rateLimiter DSL.

val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy(AdaptiveRetryStrategy) { maxAttempts = 10 rateLimiter { minFillRate = 1.0 smoothing = 0.75 } } }
Note

La stratégie de nouvelle tentative adaptative suppose que le client travaille sur une seule ressource (par exemple, une table DynamoDB ou un compartiment Amazon S3).

Si vous utilisez un seul client pour plusieurs ressources, les ralentissements ou les pannes associés à une ressource entraînent une latence accrue et des défaillances lorsque le client accède à toutes les autres ressources. Lorsque vous utilisez la stratégie de nouvelle tentative adaptative, nous vous recommandons d'utiliser un seul client pour chaque ressource.