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

Date de la dernière mise à jour : 28/05/2020

Lorsque j'essaie d'appeler ma fonction AWS Lambda en utilisant un kit SDK AWS, la fonction expire, l'exécution se bloque ou une action d'API est dupliquée. Quelle est la marche à suivre pour résoudre ces problèmes ?

Brève description

Ces problèmes peuvent survenir lorsque :

  • Vous appelez une API à distance qui tarde trop à répondre ou qui n'est pas accessible.
  • Votre appel d'API n'obtient pas de réponse dans le délai d'expiration du socket.
  • Votre appel d'API n'obtient pas de réponse dans le délai d'expiration de votre fonction Lambda.

Remarque : les appels d'API peuvent prendre plus de temps que prévu en cas de problème de connexion réseau. Les problèmes de réseau peuvent également entraîner de nouvelles tentatives et des demandes d’API dupliquées. Pour anticiper ces événements, votre fonction Lambda doit toujours être 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 retente automatiquement l'appel. La durée et le nombre de tentatives du kit SDK sont déterminées par des paramètres qui peuvent varier entre chaque kit SDK. Les valeurs par défaut de ces paramètres sont les suivantes :

Remarque : certaines valeurs peuvent être différentes pour certains services AWS.

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 corriger les problèmes de nouvelles tentatives et de délai d’expiration, passez en revue les journaux de l'appel d’API pour déterminer le problème. Ensuite, modifiez le paramètre de nombre de tentatives et du délai d’expiration du kit SDK selon vos besoins pour chaque cas d'utilisation. Pour laisser suffisamment de temps de réponse à l'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

À l'aide des journaux Amazon CloudWatch Logs, vous pouvez obtenir des détails sur les connexions ayant échoué et 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 pour le kit SDK que vous utilisez :

Dans cet exemple de journal des erreurs, 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

...

Dans cet exemple de journal des erreurs, la connexion a abouti, mais elle a expiré après une réponse trop longue (délai d’expiration de 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 l'appel d'API n'obtient pas de réponse dans le délai d'expiration de la fonction Lambda. Si l'exécution se termine en raison d'un délai d'expiration de la fonction, essayez l'une des actions suivantes :

  • Modifiez les paramètres de nouvelles tentatives dans le kit SDK afin que toutes les nouvelles tentatives soient effectuées dans le délai d’expiration.
  • Augmentez le délai d'expiration de la fonction Lambda temporairement afin de laisser suffisamment de temps à la génération des journaux du kit SDK.

Modifier les paramètres du kit SDK

Les paramètres de nombre de tentatives et de délai d'expiration du kit SDK doivent prévoir un temps suffisant pour que votre appel d'API obtienne une réponse. Pour déterminer les valeurs correctes 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 (jusqu'à une réponse correcte)
  • Indique si les tentatives doivent être effectués par le kit SDK ou par du code

Pour plus d'informations concernant la modification de ces paramètres, consultez la documentation de configuration du client SDK :

Voici des exemples qui indiquent la façon de modifier ces paramètres pour chaque exécution :

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

Exemple Python (Boto 3) :

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

JavaScript/Node.js :

// 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 Java :

// 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 .NET :

// 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
});

Consultez les exemples 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"),
}) 

Consultez l’exemple de délais d’expiration des demandes :

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ématurée 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 cette formule pour estimer le temps de base nécessaire pour le délai d'expiration de la fonction :

Retries * (Connection timeout + Socket timeout)

Supposons que le kit SDK est configuré pour 3 nouvelles tentatives, un délai de connexion de 10 secondes et un délai d'expiration de socket de 30 secondes. Dans ce cas, le délai d’expiration de votre fonction Lambda doit être d’au moins 120 secondes :

3 * (10 + 30) = 120 seconds

Ajoutez une marge de temps supplémentaire (par exemple, 20 secondes) pour gérer l’exécution de code restant :

120 + 20 = 140 seconds

Cette page vous a-t-elle été utile ?

Cette page peut-elle être améliorée ?


Vous avez besoin d'aide ?