【问题标题】:Best Practices in Serverless Framework无服务器框架的最佳实践
【发布时间】:2016-11-09 08:38:57
【问题描述】:

我是无服务器框架的新手。 学习无服务器最佳实践时。 here

我有一个关于“在您的 Lambda 代码之外初始化外部服务”的问题。 如何实施? 例如:handler.js 中的以下代码

const getOneUser = (event, callback) => {
  let response = null;
  // validate parameters
  if (event.accountid && process.env.SERVERLESS_SURVEYTABLE) {
    let docClient = new aws.DynamoDB.DocumentClient();
    let params = {
      TableName: process.env.SERVERLESS_USERTABLE,
      Key: {
        accountid: event.accountid,
      }
    };
    docClient.get(params, function(err, data) {
      if (err) {
        // console.error("Unable to get an item with the request: ", JSON.stringify(params), " along with error: ", JSON.stringify(err));
        return callback(getDynamoDBError(err), null);
      } else {
        if (data.Item) { // got response
          // compose response
          response = {
            accountid: data.Item.accountid,
            username: data.Item.username,
            email: data.Item.email,
            role: data.Item.role,
          };
          return callback(null, response);
        } else {
          // console.error("Unable to get an item with the request: ", JSON.stringify(params));
          return callback(new Error("404 Not Found: Unable to get an item with the request: " + JSON.stringify(params)), null);
        }
      }
    });
  }
  // incomplete parameters
  else {
    return callback(new Error("400 Bad Request: Missing parameters: " + JSON.stringify(event)), null);
  }
};

问题是如何在我的 Lambda 代码之外初始化 DynamoDB。

更新 2:

下面的代码优化了吗?

Handler.js

let survey = require('./survey');
module.exports.handler = (event, context, callback) => {
    return survey.getOneSurvey({
      accountid: event.accountid,
      surveyid: event.surveyid
    }, callback);
};

survey.js

let docClient = new aws.DynamoDB.DocumentClient();
module.exports = (() => {
  const getOneSurvey = (event, callback) {....
      docClient.get(params, function(err, data)...
      ....
  };

  return{
     getOneSurvey : getOneSurvey,
  }
})();

【问题讨论】:

  • “下面的代码优化了吗?” 我会说不,不是按照这个规则。每次调用handler 时,都会调用survey.getOneSurvey(),每次发生这种情况时,您都会创建一个新的aws.DynamoDB.DocumentClient。这应该只在最初加载代码时分配给适当范围的变量一次,而不是每次调用处理程序时。
  • 好的!我将 docClient 放在 module.exports 之外。它最初会加载并且只创建一个 docClient。我的想法对吗?

标签: node.js amazon-dynamodb serverless-framework


【解决方案1】:

这是有问题的报价:

在您的 Lambda 代码之外初始化外部服务

使用服务(如 DynamoDB)时,请确保在 lambda 代码之外进行初始化。例如:模块初始化器(用于 Node),或静态构造器(用于 Java)。如果您在 Lambda 函数中启动与 DDB 的连接,则该代码将在每次调用时运行。

换句话说,在同一个文件中,但在实际处理程序代码之前。

let docClient = new aws.DynamoDB...
...
const getOneUser = (event, callback) => {
....
  docClient.get(params, ...

当容器启动时,处理程序之外的代码运行。当后续函数调用重用同一个容器时,您无需再次实例化外部服务,从而节省资源和时间。容器经常被重用,但每个容器一次只处理一个并发请求,它们被重用的频率和多长时间不在你的控制范围内......除非你更新函数,在这种情况下任何现有的容器都将不再是重复使用,因为他们会使用旧版本的函数。

您的代码将按照编写的方式运行,但未经过优化。

在当前一代 Node.js Lambda 函数(Node 4.x/6.x)中出现的这种方法的警告是,某些对象(尤其是那些创建与外部服务的字面持久连接的对象)会阻止事件循环变成空(一个常见的例子是 mysql 数据库连接,它与服务器保持实时 TCP 连接;相比之下,DynamoDB“连接”实际上是无连接的,因为它的传输协议是 HTTPS)。在这种情况下,您需要在冻结容器之前采取不同的方法或allow lambda to not wait for an empty event loop,通过在调用回调之前将context.callbackWaitsForEmptyEventLoop 设置为false...但只有在需要时才这样做,并且只有在你完全理解它的情况下才这样做方法。默认设置是因为网上有人说这是个好主意,以后可能会给你带来神秘的错误。

【讨论】:

  • 感谢您的完美回答!我已经更新了我的问题!
  • 测试和模拟呢?我正在使用aws-sdk-mock,您可以在那里找到:AWS 服务需要在正在测试的函数内初始化,以便模拟 SDK 方法。因此,为了让它工作,我不得不将var dynamoDb = AWS.DynamoDB(); 移动到exports.handler = function(event, context) { See their example 2
  • @iaforek prima facie,这确实看起来是个问题,因为如果这样编写代码,它不会导致优化设计。显然(!?)每次执行处理函数时初始化对象的开销不如为每个容器只执行一次。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-26
  • 1970-01-01
  • 2020-04-07
  • 2019-10-25
  • 2010-12-21
  • 2021-09-22
相关资源
最近更新 更多