【问题标题】:Lambda INSERT INTO MySql function is adding to DB but still timing outLambda INSERT INTO MySql 函数正在添加到数据库但仍然超时
【发布时间】:2021-12-02 17:43:16
【问题描述】:

我有一个 Lambda POST 函数,它获取 http 请求 JSON 正文数据并将其添加到连接的 MySql 数据库。

代码如下:

var mysql = require("mysql");
var config = require("./config.json");

var pool = mysql.createPool({
  host: config.dbhost,
  user: config.dbuser,
  password: config.dbpassword,
  database: config.dbname,
  port: 3306,
  ssl: true,
});

exports.handler = (event, context, callback) => {
  context.callbackWaitsForEmptyjsonLoop = false;
  pool.getConnection(function (err, connection) {
    const col1 = event.col1;
    const col2 = event.col2;
    const col3 = event.col3;

    // Use the connection
    connection.query(
      "INSERT INTO table (col1, col2, col3) VALUES(?, ?, ?)",
      [col1, col2, col3],
      function (error, results, fields) {
        // And done with the connection.
        connection.release();

        var response = {
          statusCode: 200,
          body: JSON.stringify("Account added successfully!"),
        };

        // Handle error after the release.
        if (error) callback(error);
        else callback(null, response.body);
      }
    );
  });
};

我有一个非常相似的 lambda 函数,它从 JSON 更新数据库中的记录,并且运行完美。

测试代码时,记录已成功添加到数据库中。但是,无论我将超时限制设置多长时间,lambda 函数都会超时。

lambda 返回此错误:

{ "errorMessage": "2021-10-14T10:00:25.159Z 62f12d68-c648-4f0f-9e86-3cd23f0f90c6 Task timed out after 5.01 seconds" }

日志的最后两行是:

Thu Oct 14 10:00:25 UTC 2021 : Successfully completed execution
Thu Oct 14 10:00:25 UTC 2021 : Method completed with status: 200

我已将代码作为运行它的本地文件使用:node local.js 进行了测试,它运行迅速且没有错误。

不知道我错过了什么。 INSERT INTO 查询的返回类型可能与 UPDATE 不同?

任何帮助将不胜感激。谢谢

【问题讨论】:

  • 您的 lambda 在 VPC 中吗?和mysql一样吗?
  • Lambda 是区域性的。 MySql 是天蓝色的云
  • context.callbackWaitsForEmptyEventLoop = false
  • @hoangdv 你明白了,非常感谢。如果您愿意,可以发布作为答案,我会接受
  • 我仍然想指出,在您的 lambda 函数中使用完整的连接池并不是很有用(而且最终会出现问题)。通常最好只打开一个连接并在每次执行处理程序函数时再次关闭它。这也可以防止您在这里遇到的问题。

标签: node.js amazon-web-services aws-lambda aws-api-gateway


【解决方案1】:

cmets 中已经给出了关于这个问题的答案,但我想在这里更深入一点,因为在 lambda 函数中使用连接池(大多数情况下)没有用,甚至可能有害。

为什么没用

连接池旨在在您可能希望同时处理多个不同操作的应用程序中处理与数据库的多个并行连接(例如,同时处理多个请求的快速 API)。但是,AWS Lambda 旨在同时处理一个请求,并为每个并行执行提供不同的执行环境。这意味着您将从数据库中请求更多实际需要的连接。

为什么会不好

您无法控制 lambda 执行环境的终止方式。这也意味着您无法确保连接池中的连接会正常关闭,也无法确保数据库服务器会为您关闭它们。如果您随后大幅增加 lambda 执行(通过增加流量或通过在 lambda 中创建循环 - 这很容易完成),您可以很快耗尽数据库可用的所有可用连接,这可能会影响数据库的所有其他客户也是如此。这通常以与经理的一次非常不舒服的谈话结束(去过那里,做过)。

那该怎么做呢?

嗯,实际上非常简单,创建一个连接,使用它并再次关闭它。下面是这样一个处理函数的示例(使用 postgres db,但应该很容易适应使用 MySQL):

const pgp = require('pg-promise')();
const getDBConfiguration = require('./db-config');

let dbOptions; // dbOptions are retrieved from SSM param store, we can cache those
const handler = async (event) => {
  dbOptions = dbOptions || { ...(await getDBConfiguration()), max: 1 }; // restrict number of connections in pool to one

  const client = pgp(dbOptions);
  try {
    await client.any(/*Execute some query*/);
  } finally {
    await client.$pool.end();
  }
};

【讨论】:

  • 感谢您的信息!我会做一些测试,看看我能不能让它工作。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-20
  • 2018-09-03
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多