【问题标题】:AWS Lambda with Knex JS and RDS Postgres带有 Knex JS 和 RDS Postgres 的 AWS Lambda
【发布时间】:2018-01-16 17:37:28
【问题描述】:

我一直在做一些研究,但找不到关于在 Lambda 函数中使用 Knex JS 的好答案:

How do I use Knex with AWS Lambda? #1875

Serverless URL Shortener with Apex and AWS Lambda

Use Promise.all() in AWS lambda

这是我的 index.js 中的内容:

const knex = require('knex')({
  client: 'pg',
  connection: {...},
});

exports.handler = (event, context, callback) => {
  console.log('event received: ', event);
  console.log('knex connection: ', knex);

  knex('goals')
    .then((goals) => {
      console.log('received goals: ', goals);
      knex.client.destroy();
      return callback(null, goals);
    })
    .catch((err) => {
      console.log('error occurred: ', err);
      knex.client.destroy();
      return callback(err);
    });
};

我能够在本地很好地连接和执行我的代码,但是在将其部署到 AWS 时遇到了一个有趣的错误——第一次调用总是成功的,但之后的任何事情都失败了。我认为这与 knex 客户端被破坏有关,但随后又试图在下一次调用时再次使用。如果我重新上传我的 index.js,它会恢复为一个呼叫工作,然后失败。

我相信这可以使用 Promise 以某种方式解决,但这是我第一次使用 Lambda,所以我不熟悉它如何在后续调用中管理与 RDS 的连接。提前感谢您的任何建议!

【问题讨论】:

    标签: postgresql aws-lambda knex.js


    【解决方案1】:

    对我来说,它可以在我的本地机器上运行,但在部署后就不行了。我有点被误导了。

    事实证明,RDS 入站源未对我的 Lambda 函数开放。在 AWS Lambda can't connect to RDS instance, but I can locally? 找到解决方案:将 RDS 入站源更改为 0.0.0.0/0 或使用 VPC。

    更新 RDS 入站源后,我可以成功使用 Lambda 和 Knex。

    我使用的 Lambda 运行时是 Node.js 8.10,带有包:

    knex: 0.17.0
    pg: 7.11.0
    

    下面使用异步的代码也适用于我

    const Knex = require('knex');
    
    const pg = Knex({ ... });
    
    module.exports.submitForm = async (event) => {
      const {
        fields,
      } = event['body-json'] || {};
    
      return pg('surveys')
        .insert(fields)
        .then(() => {
          return {
            status: 200
          };
        })
        .catch(err => {
          return {
            status: 500
          };
        });
    };
    

    希望它能帮助将来可能遇到同样问题的人。

    【讨论】:

      【解决方案2】:

      在 AWS Lambda 中处理数据库连接最可靠的方法是在调用过程本身连接断开数据库

      在您上面的代码中,由于您在第一次调用后已经断开连接,因此第二个不再有连接。

      要修复它,只需移动 knex 的实例即可。

      exports.handler = (event, context, callback) => {
        console.log('event received: ', event);
      
        // Connect
        const knex = require('knex')({
          client: 'pg',
          connection: {...},
        });
      
        console.log('knex connection: ', knex);
      
        knex('goals')
          .then((goals) => {
            console.log('received goals: ', goals);
            knex.client.destroy();
            return callback(null, goals);
          })
          .catch((err) => {
            console.log('error occurred: ', err);
            // Disconnect
            knex.client.destroy();
            return callback(err);
          });
      };
      

      有多种方法可以重用现有连接,但成功率因数据库服务器配置和生产负载而异。

      【讨论】:

      • 如果 lambda 函数的执行率很高,您将达到连接限制。看看 - dba.stackexchange.com/q/161524/88470
      • @AdarshMadrecha 这个答案在每次调用中都会连接和断开连接,因此不太可能达到连接限制。
      • @NoelLlevares 你能详细说明你为什么这么认为吗? Lambda 将在重负载下自动扩展,并可能导致创建(或尝试创建)比数据库处理更多的数据库连接。
      【解决方案3】:

      我遇到了与您所说的完全相同的问题:在 AWS lambda 函数中使用了 destroy()(如下所示:底部的 await knex.destroy()),突然我所有的 AWS lambdas 都出错了。

      因为我没有怀疑,所以我搜索了几个小时导致问题的原因,甚至开始使用 lambda + vpc + nat 等进行调查。结果只是 AWS 冻结 lambda 的方式是如果你破坏连接,在下一次处理程序调用时,它将尝试重用连接。

      解决方案:不要在 lambda 末尾使用 .destroy() 并重新部署。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-07-27
        • 1970-01-01
        • 1970-01-01
        • 2019-05-27
        • 2021-10-13
        • 1970-01-01
        相关资源
        最近更新 更多