Tous les produits
Search
Centre de documentation

Key Management Service:Réessayer les requêtes avec un backoff exponentiel

Dernière mise à jour :Aug 24, 2026

Lorsque vous appelez les API KMS, des erreurs peuvent survenir. Cette rubrique explique comment utiliser le backoff exponentiel pour réessayer en cas d'erreur de requête.

Contexte

Lorsque vous appelez une API de service, une erreur peut survenir. Dans ce cas, vous pouvez réessayer la requête depuis votre application.

Certains SDK Alibaba Cloud prennent en charge les nouvelles tentatives automatiques via la configuration. Par exemple, le SDK Alibaba Cloud pour .NET vous permet de configurer des politiques de nouvelle tentative. Si les nouvelles tentatives automatiques ne sont pas applicables, utilisez la méthode décrite dans cette rubrique.

Stratégies de nouvelle tentative

Si une requête échoue en raison d'une erreur serveur (5xx) ou d'une erreur de limitation du débit, réessayez la requête en appliquant les stratégies suivantes :

  • Nouvelle tentative simple.

    Par exemple, réessayez chaque seconde pendant 10 secondes.

  • Backoff exponentiel.

    En cas de réponses d'erreur consécutives, l'intervalle d'attente entre les nouvelles tentatives s'allonge progressivement. Vous devez effectuer les nouvelles tentatives en fonction de l'intervalle de délai maximal et du nombre maximal de tentatives. Le backoff exponentiel permet d'éviter les conflits continus lors des nouvelles tentatives. Par exemple, lorsque les requêtes dépassent le quota de limitation du débit sur une courte période, le backoff exponentiel permet d'éviter efficacement les erreurs de limitation continues.

Important

Les passerelles KMS dédiées n'imposent pas de limite supérieure au nombre d'appels d'API. Elles adoptent plutôt une approche « best-effort » pour maximiser l'utilisation des ressources de calcul et de stockage de l'instance afin de traiter les requêtes API. Par conséquent, les erreurs de limitation du débit ne se produisent pas.

Pseudocode pour le backoff exponentiel

Le pseudocode suivant montre comment réessayer une opération en utilisant des délais incrémentiels.

initialDelay = 200
retries = 0

DO
    wait for (2^retries * initialDelay) milliseconds

    status = CallSomeAPI()

    IF status == SUCCESS
        retry = false // Succeeded, stop calling the API again.
    ELSE IF status = THROTTLED || status == SERVER_NOT_READY
        retry = true  // Failed because of throttling or server busy, try again.
    ELSE
        retry = false // Some other error occurred, stop calling the API again.
    END IF

    retries = retries + 1

WHILE (retry AND (retries < MAX_RETRIES))

Utiliser le backoff exponentiel pour gérer la limitation du débit de KMS

L'exemple Java suivant montre comment utiliser le backoff exponentiel pour gérer les erreurs de limitation du débit lorsque KMS appelle l'opération Decrypt.

  • Vous pouvez apporter de simples modifications pour réessayer des types spécifiques d'erreurs serveur, telles que HTTP 503.

  • Vous pouvez estimer le nombre de requêtes envoyées par le client sur une période donnée et ajuster le délai initial (initialDelay) ainsi que le nombre de nouvelles tentatives (maxRetries).

Remarque

Une paire AccessKey pour un compte Alibaba Cloud dispose des permissions pour toutes les opérations d'API. Nous vous recommandons d'utiliser un utilisateur RAM pour appeler les opérations d'API ou effectuer les tâches d'exploitation et de maintenance courantes. Pour prévenir les risques de sécurité, ne codez pas en dur votre AccessKey ID et votre AccessKey Secret dans le code de votre projet. Le codage en dur des identifiants peut entraîner des fuites compromettant toutes les ressources de votre compte.

Cette rubrique fournit un exemple de configuration des variables d'environnement ALIBABA_CLOUD_ACCESS_KEY_ID et ALIBABA_CLOUD_ACCESS_KEY_SECRET pour l'authentification d'identité.

import com.aliyun.kms20160120.Client;
import com.aliyun.kms20160120.models.DecryptRequest;
import com.aliyun.kms20160120.models.DecryptResponse;
import com.aliyun.tea.*;
import com.aliyun.teautil.models.RuntimeOptions;

import java.nio.charset.StandardCharsets;

public class Main {
    private static  Client kmsClient;

    private static Client kmsClient(String regionId, String accessKeyId, String accessKeySecret) throws Exception {
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
            .setAccessKeyId(accessKeyId)
            .setAccessKeySecret(accessKeySecret);
        config.setRegionId(regionId) ;
    return new Client(config);
    }

    private static String kmsDecrypt(String cipherTextBlob) throws Exception {
        DecryptRequest decryptRequest = new DecryptRequest()
                // Specify the ciphertext that you want to decrypt.
                .setCiphertextBlob(cipherTextBlob);
        DecryptResponse response = kmsClient.decryptWithOptions(decryptRequest, new RuntimeOptions());
        // Obtain the decrypted plaintext from the response.
        String plaintext = response.getBody().getPlaintext();

        System.out.println("Ciphertext (Base64): " + cipherTextBlob);
        System.out.println("Decrypted Plaintext: " + plaintext);
        return plaintext;
    }

    public static long getWaitTimeExponential(int retryCount) {
        final long initialDelay = 200L;
        long waitTime = ((long) Math.pow(2, retryCount) * initialDelay);
        return waitTime;
    }

    public static void main(String[] args) throws Exception {
        String regionId = "<region ID>"; // Example: "cn-shanghai"
        String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
        String cipherTextBlob ="a2V5LXNoaDY4M**********w=";
        int maxRetries = 5;

        kmsClient =  kmsClient(regionId, accessKeyId, accessKeySecret);

        for (int i = 0; i < maxRetries; i++) {
            try {
                String plainText = kmsDecrypt(cipherTextBlob);
                return;
            } catch (Exception e) {
                e.printStackTrace();
                if (e.getMessage().contains("Rejected.Throttling")) { // Throttled. Retry the request.
                    try {
                        Thread.sleep(getWaitTimeExponential(i + 1));
                    } catch (InterruptedException ignore) {
                    }
                } else {
                    break; // Not a throttling error. Stop retrying.
                }
            }
        }
    }
}