Wie behebe ich Wiederholungs- und Timeout-Probleme, wenn ich ein AWS-SDK verwende, um eine Lambda-Funktion aufzurufen?

Lesedauer: 6 Minute
0

Wenn ich meine AWS Lambda-Funktion mit dem AWS-SDK aufrufe, läuft die Funktion ab, die API-Anforderung schlägt fehl oder eine API-Aktion wird dupliziert.

Kurzbeschreibung

Beim Aufrufen einer Lambda-Funktion mit einem AWS-SDK können aufgrund der folgenden Bedingungen Wiederholungs- und Timeout-Probleme auftreten:

  • Eine Remote-API ist nicht erreichbar oder es dauert zu lange, bis sie auf einen API-Aufruf reagiert.
  • Der API-Aufruf erhält innerhalb des Socket-Timeouts keine Antwort.
  • Der API-Aufruf erhält innerhalb des Timeout-Zeitraums der Lambda-Funktion keine Antwort.

Hinweis: API-Aufrufe können länger als erwartet dauern, wenn Netzwerkverbindungsprobleme auftreten. Netzwerkprobleme können auch zu Wiederholungsversuchen und doppelten API-Anfragen führen. Um dich auf diese Ereignisse vorzubereiten, stelle sicher, dass die Lambda-Funktion idempotent ist.

Wenn du ein AWS-SDK für einen API-Aufruf verwendest und der Aufruf fehlschlägt, versucht das AWS-SDK den Aufruf automatisch erneut. Wie oft und wie lange das AWS-SDK dies wiederholt, hängt von den Einstellungen ab, die von AWS-SDK zu AWS-SDK variieren.

Standardeinstellungen für AWS-SDK-Wiederholungen

Hinweis: Einige Werte können für andere AWS-Services unterschiedlich sein.

AWS SDKMaximale Anzahl an WiederholungenVerbindungs-TimeoutSocket-Timeout
Python (Boto 3)hängt vom Service ab60 Sekunden60 Sekunden
JavaScript/Node.jshängt vom Service abN/A120 Sekunden
Java310 Sekunden50 Sekunden
.NET4100 Sekunden300 Sekunden
Go3N/AN/A

Um die Probleme mit Wiederholungsversuchen und Timeout zu beheben, überprüfe zunächst die Protokolle des API-Aufrufs, um das Problem zu finden. Ändere dann die Anzahl der Wiederholungsversuche und die Timeout-Einstellungen des AWS-SDK nach Bedarf für jeden Anwendungsfall. Um genügend Zeit für eine Antwort auf den API-Aufruf zu haben, füge der Timeout-Einstellung der Lambda-Funktion Zeit hinzu.

Lösung

Protokolliere die API-Aufrufe des AWS-SDK

Verwende Amazon CloudWatch Logs, um Details über fehlgeschlagene Verbindungen und die Anzahl der jeweils versuchten Wiederholungsversuche abzurufen. Weitere Informationen findest du unter Verwenden von CloudWatch Logs-Protokollen mit Lambda. Oder sieh dir die folgenden Anweisungen für das AWS-SDK an, das du verwendest:

Beispiel für ein Fehlerprotokoll, in dem der API-Aufruf keine Verbindung herstellen konnte (Verbindungs-Timeout)

START RequestId: b81e56a9-90e0-11e8-bfa8-b9f44c99e76d Version: $LATEST2018-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

...

Beispiel für ein Fehlerprotokoll, in dem die API-Aufrufverbindung erfolgreich war, aber ein Timeout aufgetreten ist, nachdem die API-Antwort zu lange gedauert hat (Socket-Timeout)

START RequestId: 3c0523f4-9650-11e8-bd98-0df3c5cf9bd8 Version: $LATEST2018-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

Hinweis: Diese Protokolle werden nicht generiert, wenn die API-Anfrage innerhalb des Timeouts deiner Lambda-Funktion keine Antwort erhält. Wenn die API-Anfrage aufgrund eines Funktions-Timeouts endet, versuche einen der folgenden Schritte:

Ändere die Einstellungen des AWS-SDK

Die Einstellungen für die Anzahl der Wiederholungen und das Timeout des AWS-SDK sollten ausreichend Zeit für deinen API-Aufruf bieten, um eine Antwort zu erhalten. Um die richtigen Werte für jede Einstellung zu ermitteln, teste verschiedene Konfigurationen und hole dir die folgenden Informationen:

  • Durchschnittliche Zeit bis zum Aufbau einer erfolgreichen Verbindung
  • Durchschnittliche Zeit, die eine vollständige API-Anforderung benötigt, bis sie erfolgreich zurückgegeben wird

Weitere Informationen zum Ändern der Anzahl der Wiederholungen und der Timeout-Einstellungen findest du in der folgenden Dokumentation zur Konfiguration des AWS-SDK-Clients:

Im Folgenden findest du einige Beispielbefehle, mit denen die Anzahl der Wiederholungsversuche und die Timeout-Einstellungen für jede Laufzeit geändert werden.

Hinweis: Achte darauf, die Beispielwerte für jede Einstellung durch die Werte für deinen Anwendungsfall zu ersetzen.

Beispiel für einen Python-Befehl (Boto 3) zum Ändern der Anzahl der Wiederholungsversuche und der Timeout-Einstellungen

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

Beispielbefehl JavaScript/Node.js zum Ändern der Anzahl der Wiederholungsversuche und der Timeout-Einstellungen

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

    }

});

Beispielbefehl JavaScript V3 zum Ändern der Anzahl der Wiederholungsversuche und der Timeout-Einstellungen

const { S3Client, ListBucketsCommand } = require("@aws-sdk/client-s3");
const { NodeHttpHandler } = require("@aws-sdk/node-http-handler");
const client = new S3Client({
    requestHandler: new NodeHttpHandler({
        connectionTimeout: 30000,
        socketTimeout: 50000
    }),
    maxAttempts: 2
});

Beispiel für einen Java-Befehl zum Ändern der Anzahl der Wiederholungsversuche und der Timeout-Einstellungen

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

.NET-Beispielbefehl zum Ändern der Anzahl der Wiederholungsversuche und der Timeout-Einstellungen

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

Beispiel für einen Go-Befehl zum Ändern der Einstellungen für die Anzahl der Wiederholungen

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

Beispiel für einen Go-Befehl zum Ändern der Timeout-Einstellungen für Anfragen

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

(Optional) Änderung der Timeout-Einstellung der Lambda-Funktion

Ein niedriger Timeout für die Lambda-Funktion kann dazu führen, dass fehlerfreie Verbindungen vorzeitig unterbrochen werden. Erhöhe die Timeout-Einstellung für Funktionen, damit der API-Aufruf genügend Zeit hat, eine Antwort zu erhalten.

Verwende die folgende Formel, um die für den Funktions-Timeout benötigte Basiszeit abzuschätzen:

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

Beispiel für eine Timeout-Berechnung für eine Lambda-Funktion

Hinweis: Die folgende Berechnung bezieht sich auf ein AWS-SDK, das für drei Wiederholungsversuche, ein 10-Sekunden-Verbindungs-Timeout und ein 30-Sekunden-Socket-Timeout konfiguriert ist.

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

Ähnliche Informationen

Aufrufen

Grundlegendes zum Wiederholungsverhalten in Lambda

Lambda-Kontingente

AWS OFFICIAL
AWS OFFICIALAktualisiert vor 5 Monaten