¿Cómo soluciono los problemas de reintento y tiempo de espera al invocar una función de Lambda mediante un AWS SDK?

8 minutos de lectura
0

Cuando invoco mi función de AWS Lambda mediante un AWS SDK, se agota el tiempo de espera de la función, la solicitud de la API deja de responder o se duplica una acción de la API. ¿Cómo soluciono estos problemas?

Breve descripción

Hay tres motivos por los que se producen problemas de reintento y de tiempo de espera al invocar una función de Lambda con un AWS SDK:

  • No se puede acceder a una API remota o tarda demasiado en responder a una llamada a la API.
  • La llamada a la API no recibe respuesta dentro del tiempo de espera del socket.
  • La llamada a la API no recibe respuesta dentro del periodo de tiempo de espera de la función de Lambda.

Nota: Las llamadas a la API pueden tardar más de lo esperado cuando se producen problemas de conexión a la red. Los problemas de red también pueden provocar reintentos y solicitudes de API duplicadas. Para prepararse para estos casos, asegúrese de que la función de Lambda sea idempotente.

Si realiza una llamada a la API con un AWS SDK y la llamada falla, AWS SDK vuelve a intentar realizar la llamada automáticamente. La cantidad de veces que AWS SDK reintenta las llamadas y durante cuánto tiempo depende de la configuración, que varía de un AWS SDK a otro.

Configuración de reintento predeterminada de AWS SDK

Nota: Algunos valores pueden ser diferentes para otros servicios de AWS.

AWS SDKNúmero máximo de reintentosTiempo de espera de conexiónTiempo de espera del socket
Python (Boto 3)En función del servicio60 segundos60 segundos
JavaScript/Node.jsEn función del servicioN/D120 segundos
Java310 segundos50 segundos
.NET4100 segundos300 segundos
Go3N/DN/D

Para solucionar los problemas de reintento y tiempo de espera, primero revise los registros de la llamada a la API para localizar el problema. A continuación, cambie la configuración del número de reintentos y el tiempo de espera de AWS SDK según sea necesario en cada caso. Para dejar suficiente tiempo para responder a la llamada a la API, añada un tiempo a la configuración del tiempo de espera de la función de Lambda.

Resolución

Registro de las llamadas a la API realizadas por AWS SDK

Utilice los Registros de Amazon CloudWatch para obtener detalles sobre las conexiones fallidas y el número de reintentos para cada una de ellas. Para obtener más información, consulte Acceso a los registros de Amazon CloudWatch para AWS Lambda. También puede consultar las siguientes instrucciones para el AWS SDK que esté utilizando:

Ejemplo de registro de errores en el que la llamada a la API no pudo establecer una conexión (tiempo de espera de conexión)

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

...

Ejemplo de registro de errores en el que la conexión a la llamada a la API se realizó correctamente, pero se agotó el tiempo de espera después de que la respuesta a la API tardara demasiado (tiempo de espera del socket)

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

Nota: Estos registros no se generan si la solicitud de la API no recibe una respuesta dentro del tiempo de espera de la función de Lambda. Si la solicitud de la API finaliza debido a que se ha agotado el tiempo de espera de una función, pruebe una de las siguientes opciones:

Cambio de la configuración de AWS SDK

La configuración del número de reintentos y el tiempo de espera de AWS SDK deberían permitir tiempo suficiente para que la llamada a la API reciba una respuesta. Para determinar los valores correctos para cada ajuste, pruebe diferentes configuraciones y obtenga la siguiente información:

  • Tiempo promedio para establecer una conexión satisfactoria
  • Tiempo promedio que tarda una solicitud de API completa (hasta que se devuelva correctamente)
  • Si los reintentos deben realizarse mediante SDK AWS o código

Para obtener más información sobre cómo cambiar la configuración del número de reintentos y el tiempo de espera, consulte la siguiente documentación sobre configuración del cliente AWS SDK:

A continuación se muestran algunos comandos de ejemplo que cambian la configuración del número de reintentos y el tiempo de espera para cada tiempo de ejecución.

Importante: Antes de usar cualquiera de los siguientes comandos, sustituya los valores de ejemplo de cada configuración por los valores de su caso.

Ejemplo de comando de Python (Boto 3) para cambiar la configuración del número de reintentos y el tiempo de espera

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

Ejemplo de comando de JavaScript/Node.js para cambiar la configuración del número de reintentos y el tiempo de espera

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

    }

});

Ejemplo de comando de Java para cambiar la configuración del número de reintentos y el tiempo de espera

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

Ejemplo de comando de .NET para cambiar la configuración del número de reintentos y el tiempo de espera

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

Ejemplo de comando de Go para cambiar la configuración del número de reintentos

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

Ejemplo de comando de Go para cambiar la configuración del tiempo de espera de la solicitud

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()

(Opcional) Cambio de la configuración de tiempo de espera de la función de Lambda

Un tiempo de espera bajo de la función de Lambda puede provocar que las conexiones en buen estado se interrumpan antes de tiempo. Si esto ocurre en su caso, aumente el ajuste del tiempo de espera de la función con el fin de que su llamada a la API tenga tiempo suficiente para obtener una respuesta.

Utilice la siguiente fórmula para calcular el tiempo de base necesario para el tiempo de espera de la función:

First attempt (connection timeout + socket timeout) + Number of retries x (connection timeout + socket timeout) + 20 seconds additional code runtime margin = Required Lambda function timeout

Ejemplo de cálculo del tiempo de espera de la función de Lambda

Nota: El siguiente cálculo es para un AWS SDK configurado para tres reintentos, un tiempo de espera de conexión de diez segundos y un tiempo de espera del socket de treinta segundos.

First attempt (10 seconds + 30 seconds) + Number of retries [3 * (10 seconds + 30 seconds)] + 20 seconds additional code runtime margin = 180 seconds

Información relacionada

Invoke (referencia de la API de Lambda)

Control de errores y reintentos automáticos en AWS Lambda

Cuotas de Lambda

OFICIAL DE AWS
OFICIAL DE AWSActualizada hace 2 años