Comment résoudre les problèmes de nouvelles tentatives et de délai d'expiration lors de l'appel d'une fonction Lambda à l'aide d'un kit SDK AWS ?

Dernière mise à jour : 18/03/2021

Lorsque j'appelle ma fonction AWS Lambda à l'aide d'un kit SDK AWS, la fonction expire, la demande d'API cesse de répondre ou une action d'API est dupliquée. Comment résoudre ces erreurs ?

Brève description

Trois raisons permettent d'expliquer pourquoi des problèmes de nouvelles tentatives et de délai d'expiration se produisent lors de l'appel d'une fonction Lambda à l'aide d'un kit SDK AWS :

  • Une API distante est injoignable ou met trop de temps à répondre à un appel d'API.
  • L'appel d'API n'obtient pas de réponse dans le délai d'expiration du socket.
  • L'appel d'API n'obtient pas de réponse dans le délai d'expiration de la fonction Lambda.

Remarque : les appels d'API peuvent prendre plus de temps que prévu lorsque des problèmes de connexion réseau surviennent. Les problèmes de réseau peuvent également entraîner de nouvelles tentatives et des demandes d'API en double. Pour vous y préparer, assurez-vous que votre fonction Lambda est idempotente.

Si vous effectuez un appel d'API à l'aide d'un kit de développement logiciel (SDK) AWS et que l'appel échoue, le kit SDK AWS retente automatiquement l'appel. Le nombre de tentatives du kit SDK AWS et leur durée sont déterminés par des paramètres qui varient d'un kit SDK AWS à l'autre.

Paramètres de nouvelles tentatives par défaut du kit SDK AWS

Remarque : certaines valeurs peuvent varier d'un service AWS à l'autre.

KIT SDK AWS Nombre maximal de nouvelles tentatives Délai d'expiration de la connexion Délai d'expiration du socket
Python (Boto 3) dépend du service 60 secondes 60 secondes
JavaScript/Node.js dépend du service N/A 120 secondes
Java 3 10 secondes 50 secondes
.NET 4 100 secondes 300 secondes
Go 3 N/A N/A

Pour résoudre les problèmes de nouvelles tentatives et de délai d'expiration, commencez par passer en revue les journaux de l'appel d'API afin d'identifier le problème. Ensuite, modifiez les paramètres de nombre de tentatives et de délai d'expiration du kit SDK AWS en fonction des besoins de chaque cas d'utilisation. Pour avoir le temps de recevoir une réponse après un appel d'API, ajoutez du temps au paramètre de délai d'expiration de la fonction Lambda.

Résolution

Consignez les appels d'API effectués par le kit SDK AWS

À l'aide des journaux Amazon CloudWatch Logs, vous pouvez obtenir des détails sur les échecs de connexion et sur le nombre de nouvelles tentatives. Pour plus d'informations, consultez Accès aux journaux Amazon CloudWatch Logs pour AWS Lambda. Vous pouvez également consulter les instructions relatives au kit SDK AWS que vous utilisez :

Exemple de journal d'erreurs dans lequel l'appel d'API n'a pas réussi à établir une connexion (délai d'expiration du socket)

START RequestId: b81e56a9-90e0-11e8-bfa8-b9f44c99e76d Version: $LATEST
2018-07-26T14:32:27.393Z    b81e56a9-90e0-11e8-bfa8-b9f44c99e76d    [AWS ec2 undefined 40.29s 3 retries] describeInstances({})
2018-07-26T14:32:27.393Z    b81e56a9-90e0-11e8-bfa8-b9f44c99e76d    { TimeoutError: Socket timed out without establishing a connection

...

Exemple de journal d'erreurs dans lequel la connexion a expiré parce que l'API a mis trop longtemps à répondre (délai d'expiration de la connexion)

START RequestId: 3c0523f4-9650-11e8-bd98-0df3c5cf9bd8 Version: $LATEST
2018-08-02T12:33:18.958Z    3c0523f4-9650-11e8-bd98-0df3c5cf9bd8    [AWS ec2 undefined 30.596s 3 retries] describeInstances({})
2018-08-02T12:33:18.978Z    3c0523f4-9650-11e8-bd98-0df3c5cf9bd8    { TimeoutError: Connection timed out after 30s

Remarque : ces journaux ne sont pas générés si la demande d'API n'obtient pas de réponse dans le délai d'expiration de la fonction Lambda. Si la demande d'API se termine en raison d'un délai d'expiration de la fonction, essayez l'une des actions suivantes :

Modifiez les paramètres du kit SDK AWS

Les paramètres de nombre de tentatives et de délai d'expiration du kit SDK AWS doivent prévoir un temps suffisant pour que votre appel d'API obtienne une réponse. Afin de déterminer les bonnes valeurs pour chaque paramètre, testez différentes configurations et obtenez les informations suivantes :

  • Temps moyen pour établir une connexion réussie
  • Durée moyenne d'une demande d'API complète (jusqu'à obtention d'une réponse correcte)
  • Si les tentatives doivent être effectuées par le kit SDK AWS ou par le code

Pour plus d'informations sur la modification des paramètres de nombre de nouvelles tentatives et de délai d'expiration, consultez la documentation de configuration du client SDK AWS :

Vous trouverez ci-dessous quelques exemples de commandes qui modifient les paramètres de nombre de nouvelles tentatives et de délai d'expiration pour chaque exécution.

Important : avant d'utiliser les commandes suivantes, remplacez les exemples de valeurs de chaque paramètre par les valeurs de votre cas d'utilisation.

Exemple de commande Python (Boto 3) permettant de modifier les paramètres de nombre de nouvelles tentatives et de délai d'expiration

# max_attempts: retry count / read_timeout: socket timeout / connect_timeout: new connection timeout

from botocore.session import Session
from botocore.config import Config

s = Session()
c = s.create_client('s3', config=Config(connect_timeout=5, read_timeout=60, retries={'max_attempts': 2}))

Exemple de commande JavaScript/Node.js permettant de modifier les paramètres de nombre de nouvelles tentatives et de délai d'expiration

// maxRetries: retry count / timeout: socket timeout / connectTimeout: new connection timeout

var AWS = require('aws-sdk');

AWS.config.update({

    maxRetries: 2,

    httpOptions: {

        timeout: 30000,

        connectTimeout: 5000

    }

});

Exemple de commande Java permettant de modifier les paramètres de nombre de nouvelles tentatives et de délai d'expiration

// setMaxErrorRetry(): retry count / setSocketTimeout(): socket timeout / setConnectionTimeout(): new connection timeout

ClientConfiguration clientConfig = new ClientConfiguration(); 

clientConfig.setSocketTimeout(60000); 
clientConfig.setConnectionTimeout(5000);
clientConfig.setMaxErrorRetry(2);

AmazonDynamoDBClient ddb = new AmazonDynamoDBClient(credentialsProvider,clientConfig);

Exemple de commande .NET permettant de modifier les paramètres de nombre de nouvelles tentatives et de délai d'expiration

// MaxErrorRetry: retry count / ReadWriteTimeout: socket timeout / Timeout: new connection timeout

var client = new AmazonS3Client(

    new AmazonS3Config {
        Timeout = TimeSpan.FromSeconds(5),
        ReadWriteTimeout = TimeSpan.FromSeconds(60),
        MaxErrorRetry = 2
});

Exemple Commande Go permettant de modifier les paramètres de nombre de nouvelles tentatives

// Create Session with MaxRetry configuration to be shared by multiple service clients.
sess := session.Must(session.NewSession(&aws.Config{
    MaxRetries: aws.Int(3),
}))
 
// Create S3 service client with a specific Region.
svc := s3.New(sess, &aws.Config{
    Region: aws.String("us-west-2"),
})

Exemple de commande Go permettant de modifier les paramètres de délai d'expiration d'une demande

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// SQS ReceiveMessage
params := &sqs.ReceiveMessageInput{ ... }
req, resp := s.ReceiveMessageRequest(params)
req.HTTPRequest = req.HTTPRequest.WithContext(ctx)
err := req.Send()

(Facultatif) Modifiez le paramètre de délai d'expiration de votre fonction Lambda

Un délai d'expiration court pour la fonction Lambda peut entraîner la suppression précoce de connexions saines. Si cela se produit dans votre cas d'utilisation, augmentez le délai d'expiration de la fonction afin de laisser suffisamment de temps pour que votre appel d'API obtienne une réponse.

Utilisez la formule suivante pour estimer le temps de base nécessaire au délai d'expiration de la fonction :

First attempt (connection timeout + socket timeout) + Number of retries x (connection timeout + socket timeout)

Par exemple, supposons que le kit SDK AWS est configuré pour trois nouvelles tentatives, un délai d'expiration de la connexion de 10 secondes et un délai d'expiration du socket de 30 secondes. Dans ce cas, le délai d'expiration de la fonction Lambda doit être d'au moins 160 secondes :

First attempt (10 seconds + 30 seconds) + Number of retries [3 * (10 seconds + 30 seconds)] = 160 seconds

Ajoutez une marge supplémentaire (par exemple, 20 secondes) pour gérer le reste de l'exécution du code :

160 + 20 = 180 seconds

Cet article vous a-t-il été utile ?


Besoin d'aide pour une question technique ou de facturation ?