AWS Lamda/API 网关每两次调用都会导致内部服务器错误

AWS Lamda/API Gateway Every Second Call Results in Internal Server Error

我需要 'Nodejs' 和 'Serveless'。我创建了 'Serverless' API 并部署到 AWS。一切都按预期工作。我遇到的问题是,我似乎找不到任何相关信息,每次调用时我都会收到内部服务器错误。第一次调用是,returns 数据符合预期。

我只在开发阶段部署到 AWS。我想知道是否缺少某些配置或其他什么?

如果您需要 'Serverless' 配置或代码示例,我可以提供。

谢谢。

回答

我认为数据库调用有问题,没有及时为回调返回数据,因此我发现结果不一致。

所以基本上我所做的就是创建一个数据库class 像这样返回 Promises...

'use strict';

const mysql = require('mysql');

/**
 * Database
 */
class Database {

    constructor(config) {
        if (!this.dbConnection) {

            console.log('connect to DB');

            this.dbConnection = mysql.createPool(config);

            this.dbConnection.on('connection', (connection) => {
                console.info('Connection Made!');
            });
        }
    }

    query(sql, args) {

        return new Promise((resolve, reject) => {

            this.dbConnection.query(sql, args, (err, rows) => {
                if (err) {
                    reject(err);
                }

                resolve(rows);
            })
        });
    }

    close() {
        return new Promise((resolve, reject) => {

            this.dbConnection.end((error) => {

                if (error) {
                    reject(error);
                }

                resolve();
            });
        });
    }
}

module.exports = Database;

所以当我进行查询时,有一个结果可供回调。

'use strict';

const Database = require('./lib/Database');
const {successResponse, errorResponse} = require('./lib/response');
const CategoryResource = require('./resource/Category');

module.exports.list = (event, context, callback) => {

    let sql = 'SELECT * FROM categories AS c WHERE c.company_id = ? AND c.parent_id IS NULL AND c.status = 1 LIMIT ?, ?;';
    const company = parseInt(event.queryStringParameters.company);

    let page = 1;
    let limit = 20;

    if (null != event.queryStringParameters) {
        if ('page' in event.queryStringParameters) {
            page = parseInt(event.queryStringParameters.page);
        }

        if ('limit' in event.queryStringParameters) {
            limit = parseInt(event.queryStringParameters.limit);
        }
    }

    let start = (page - 1) * limit;

    if (isNaN(company)) {
        callback(null, errorResponse(400, 'Company ID Required', 'Parameter company_id is required.', []));
        return;
    }

    let Category = new Database();
    let categoryResource = [];

    Category
        .query(sql, [company, start, limit])
        .then(response => {

            Category.close();

            response.forEach((category) => {
                categoryResource.push(CategoryResource(category));
            });

            callback(null, successResponse(200, {
                "total": response.length,
                "perPage": limit,
                "currentPage": page,
                "data": categoryResource
            }));

        })
        .catch((error) => {

            callback(null, errorResponse(error.code, error.sqlMessage, error.sql, {
                code: error.errno,
                field: error.sqlMessage,
                message: error.sqlMessage
            }));

            Category.close();
        });
};

我希望能帮助 运行 遇到同样问题的任何人。

如果您每隔一段时间就收到一个内部服务器错误,这意味着您的代码在语法上是正确的,但存在某种逻辑错误。没有示例代码是不可能提供帮助的,但是我见过的一些只偶尔发生的更常见的错误可能是:

  • 竞争条件(例如,如果您正在对同一个数组进行并行访问)
  • 数组访问错误(长度+1 而不是长度-1、小于零,或者您的迭代器在内存中跳转到它们不应该跳到的某个地方)
  • 简单地提到了错误的变量(例如,把 i 而不是 j)

不幸的是,没有具体的例子,我们能提供的最好的就是疯狂的猜测和个人经验。您是否尝试查看 AWS 的 CloudWatch 以及它对您的执行情况的评价?那里也应该记录了一些错误。

我认为数据库调用有问题,没有及时为回调返回数据,因此我发现结果不一致。

所以基本上我所做的就是创建一个数据库class 像这样返回 Promises...

'use strict';

const mysql = require('mysql');

/**
 * Database
 */
class Database {

    constructor(config) {
        if (!this.dbConnection) {

            console.log('connect to DB');

            this.dbConnection = mysql.createPool(config);

            this.dbConnection.on('connection', (connection) => {
                console.info('Connection Made!');
            });
        }
    }

    query(sql, args) {

        return new Promise((resolve, reject) => {

            this.dbConnection.query(sql, args, (err, rows) => {
                if (err) {
                    reject(err);
                }

                resolve(rows);
            })
        });
    }

    close() {
        return new Promise((resolve, reject) => {

            this.dbConnection.end((error) => {

                if (error) {
                    reject(error);
                }

                resolve();
            });
        });
    }
}

module.exports = Database;

所以当我进行查询时,有一个结果可供回调。

'use strict';

const Database = require('./lib/Database');
const {successResponse, errorResponse} = require('./lib/response');
const CategoryResource = require('./resource/Category');

module.exports.list = (event, context, callback) => {

    let sql = 'SELECT * FROM categories AS c WHERE c.company_id = ? AND c.parent_id IS NULL AND c.status = 1 LIMIT ?, ?;';
    const company = parseInt(event.queryStringParameters.company);

    let page = 1;
    let limit = 20;

    if (null != event.queryStringParameters) {
        if ('page' in event.queryStringParameters) {
            page = parseInt(event.queryStringParameters.page);
        }

        if ('limit' in event.queryStringParameters) {
            limit = parseInt(event.queryStringParameters.limit);
        }
    }

    let start = (page - 1) * limit;

    if (isNaN(company)) {
        callback(null, errorResponse(400, 'Company ID Required', 'Parameter company_id is required.', []));
        return;
    }

    let Category = new Database();
    let categoryResource = [];

    Category
        .query(sql, [company, start, limit])
        .then(response => {

            Category.close();

            response.forEach((category) => {
                categoryResource.push(CategoryResource(category));
            });

            callback(null, successResponse(200, {
                "total": response.length,
                "perPage": limit,
                "currentPage": page,
                "data": categoryResource
            }));

        })
        .catch((error) => {

            callback(null, errorResponse(error.code, error.sqlMessage, error.sql, {
                code: error.errno,
                field: error.sqlMessage,
                message: error.sqlMessage
            }));

            Category.close();
        });
};

我希望能帮助 运行 遇到同样问题的任何人。