简体   繁体   English

无服务器框架中的最佳实践

[英]Best Practices in Serverless Framework

I am new beginner in serverless framwork. 我是无服务器框架的新手。 When study Best Practices in Serverless. 学习无服务器时的最佳实践。 here 这里

I have a question about "Initialize external services outside of your Lambda code". 我有一个关于“在Lambda代码之外初始化外部服务”的问题。 How to implement it? 怎么实现呢? For example: Below code in handler.js 例如:在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);
  }
};

The question is that how to initial DynamoDB outside of my Lambda code. 问题是如何在Lambda代码之外初始化DynamoDB。

Update 2: 更新2:

Is below code optimized? 下面的代码优化了吗?

Handler.js Handler.js

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

survey.js survey.js

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

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

Here's the quote in question: 这是有问题的引用:

Initialize external services outside of your Lambda code 在Lambda代码之外初始化外部服务

When using services (like DynamoDB) make sure to initialize outside of your lambda code. 使用服务(如DynamoDB)时,请确保在lambda代码之外进行初始化。 Ex: module initializer (for Node), or to a static constructor (for Java). 例如:模块初始化器(用于节点)或静态构造器(用于Java)。 If you initiate a connection to DDB inside the Lambda function, that code will run on every invoke. 如果在Lambda函数内启动与DDB的连接,则该代码将在每次调用时运行。

In other words, in the same file, but outside of -- before -- the actual handler code. 换句话说,在同一个文件中,但在 - 之前 - 实际的处理程序代码之外。

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

When the container starts, the code outside the handler runs. 容器启动时,处理程序外部的代码运行。 When subsequent function invocations reuse the same container, you save resources and time by not instantiating the external services again. 当后续函数调用重用同一容器时,通过不再次实例化外部服务来节省资源和时间。 Containers are often reused, but each container only handles one concurrent request at a time, and how often they are reused and for how long is outside your control... Unless you update the function, in which case any existing containers will no longer be reused, because they'd have the old version of the function. 容器经常被重用,但每个容器一次只处理一个并发请求,它们被重用的频率以及控制之外的时间......除非你更新函数,否则任何现有的容器将不再是重用,因为他们有旧版本的功能。

Your code will work as written, but isn't optimized. 您的代码将按书面形式工作,但未进行优化。

The caveat with this approach that arises in current generation Node.js Lambda functions (Node 4.x/6.x) is that some objects -- notably, those that create literal persistent connections to external services -- will prevent the event loop from becoming empty (a common example is a mysql database connection, which is holding a live TCP connection to the server; by contrast, a DynamoDB "connection" is actually connectionless, since it's transport protocol is HTTPS). 在当前生成的Node.js Lambda函数(Node 4.x / 6.x)中出现的这种方法的警告是,某些对象 - 特别是那些创建与外部服务的文字持久连接的对象 - 将阻止事件循环变为空(一个常见的例子是mysql数据库连接,它与服务器保持实时TCP连接;相比之下,DynamoDB“连接”实际上是无连接的,因为它的传输协议是HTTPS)。 In this case you need to either take a different approach or allow lambda to not wait for an empty event loop before freezing the container, by setting context.callbackWaitsForEmptyEventLoop to false before calling the callback... but only do this if needed and only if you fully understand what it means. 在这种情况下,您需要采取不同的方法或允许lambda在冻结容器之前不等待空事件循环 ,方法是在调用回调之前将context.callbackWaitsForEmptyEventLoop设置为false ...但仅在需要时才执行此操作,并且仅在你完全明白这意味着什么。 Setting it by default because some guy on the Internet said it was a good idea will potentially bring you mysterious bugs, later. 默认情况下设置它,因为互联网上的某些人说这是一个好主意,可能会带来神秘的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM