AWS: Zufälliger API-Gateway-502-Fehler mit Runtime-Segmentierungsfehlern

AWS: Zufälliger API-Gateway-502-Fehler mit Runtime-Segmentierungsfehlern

Ich verwende AWS und habe eine API, die über ein API-Gateway aufgerufen wird, das eine Node.js-Lambda-Funktion aufruft.

Sehr oft, aber zufällig, erhalte ich 502 Antworten, aber wenn ich es sofort erneut mit genau derselben Anfrage versuche, erhalte ich eine normale Antwort. Also beschloss ich, die Protokolle zu durchsuchen, um zu sehen, ob ich irgendwelche Probleme finden konnte.

Folgendes habe ich zu einer der Anfragen gefunden:

RequestId: xxxxx Error: Runtime exited with error: signal: segmentation fault Runtime.ExitError

sowie:

xxxx    ERROR   Uncaught Exception  
{
    "errorType": "Error",
    "errorMessage": "Quit inactivity timeout",
    "code": "PROTOCOL_SEQUENCE_TIMEOUT",
    "fatal": true,
    "timeout": 30000,
    "stack": [
        "Error: Quit inactivity timeout",
        "    at Quit.<anonymous> (/opt/nodejs/node_modules/mysql/lib/protocol/Protocol.js:160:17)",
        "    at Quit.emit (node:events:527:28)",
        "    at Quit.emit (node:domain:475:12)",
        "    at Quit._onTimeout (/opt/nodejs/node_modules/mysql/lib/protocol/sequences/Sequence.js:124:8)",
        "    at Timer._onTimeout (/opt/nodejs/node_modules/mysql/lib/protocol/Timer.js:32:23)",
        "    at listOnTimeout (node:internal/timers:559:17)",
        "    at processTimers (node:internal/timers:502:7)"
    ]
}

das Folgende ist mein wiederverwendbarer SQL-Connector:

const CustomSecret = require('../secrets/CustomSecret');
const mysql = require("mysql");

module.exports = class MySqlConnect {

    databaseCredObject;

    constructor() {
    }

    async queryDb(sql, args) {

        if (!this.databaseCredObject) {
            await this.fetchSecret();
        }

        let connection = null;
        const connection_settings = {
            host: this.databaseCredObject.host,
            user: this.databaseCredObject.username,
            password: this.databaseCredObject.password,
            database: 'logbook'
        };

        connection = mysql.createConnection(connection_settings);

        return new Promise((resolve, reject) => {
            connection.connect(function (err) {
                if (err) {
                    console.log('error when connecting to db:', err);
                } else {
                    console.log('Connected');
                    connection.query(sql, args, function (err, result) {
                        connection.end();
                        if (err) {
                            return reject(err);
                        }
                        return resolve(result);
                    });
                }
            });
        });
    }

    async fetchSecret() {
        const databaseCredString = await CustomSecret.getSecret('secretname', 'eu-west-2');
        this.databaseCredObject = JSON.parse(databaseCredString);
    }
}

Abschließend noch ein Beispiel meiner Lambda-Funktion (gekürzte Version):

const {compress, decompress} = require("compress-json");

const MySqlConnect = require("customPackagePath/MySqlConnect");
const CustomJwt = require("customPackagePath/CustomJwt");
const AWS = require("aws-sdk");
const warmer = require("lambda-warmer");

exports.handler = async (event) => {


    if (await warmer(event)) {
        console.log("Warming");
        return 'warmed';
    }

    let responseCode = 200;
    let response = {};

    response.headers = {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
    };

    const bodyContent = JSON.parse(event.body);
    const dataType = bodyContent.dataType;
    const webAuth = new CustomJwt();
    const decodedToken = webAuth.decodeToken(event.headers.Authorization);
    const userUUID = decodedToken['uuid'];
    
    
    const connection = new MySqlConnect();
    
    let sql;

    switch (dataType) {
        case 'userPreferences':
            sql = await connection.queryDb('SELECT * FROM user WHERE uuid = ?', [userUUID]);
            break;
    }


    let data = [];

    for (let index in sql) {
        data.push(JSON.parse(JSON.stringify(sql[index])));

    }


    const returnData = {
        data
    };


    let compressed = compress(returnData);

    response.statusCode = responseCode;
    response.body = JSON.stringify(compressed);


    return response;
};

Ich bin neu in Sachen Infrastruktur. Aber mir scheint, dass eine Lambda-Funktion, sobald sie aufgerufen wurde, nicht richtig geschlossen oder beendet wird. Außerdem verwende ich den Lambda-Wärmer, um die Funktionen warm zu halten, wie im Lambda-Code zu sehen, und bin mir nicht sicher, ob das irgendwelche Probleme verursacht.

Ich bin für jede Hilfe dankbar, da ich einfach nicht dahinterkomme.

Danke

Antwort1

Nach weiteren Recherchen habe ich beschlossen, meiner Lambda-Funktion Folgendes hinzuzufügen:

exports.handler = async (event, context, callback) => {

und die Rückkehr so

callback(null, response);

und seitdem scheint dieses Problem gelöst zu sein. Ich bin mir nicht ganz sicher, warum, aber im Moment sieht es gut aus :)

Teilen Bearbeiten Löschen

verwandte Informationen