为什么AWS Lambda功能总是超时?

时间:2017-01-12 19:50:58

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

我正在测试aws lambda,使用4.3版本的nodejs。我能够在控制台测试中成功完成处理程序功能中的所有语句,包括连接到我们的vpc中的mongodb主机。但是,该功能总是超时。我发现了几个讨论使用回调,设置上下文属性和IAM角色权限的帖子和资源,但无论我做什么,它总是会超时。目前的代码:

'use strict';

var Mongoose = require('mongoose');
var Device = require('./device_model');
var Alarm = require('./alarm_model');
var Event = require('./event_model');

var mongoConnection = process.env.MONGO_URL;

var connection = Mongoose.connect(mongoConnection);

Mongoose.connection.once('open', function() {
    console.log("Connecting to mongo at: " + mongoConnection);
    console.log("Mongoose connection in lambda opened");
});

Mongoose.connection.on('error', function(){
    console.error("Error creating mongoose connection in lambda, exiting!");
    process.exit(1);
});

exports.check_alarms = function(event, context, callback) {

    context.callbackWaitsForEmtpyEventLoop = false;
    console.log("The incoming event: " + JSON.stringify(event));

    var device = null;
    Device.findByUUID(event.uuid, function(error, result){
        if(!error){
            device = result;
            console.log("the device: " + JSON.stringify(device));
            if(event.Ale && event.Ale.length > 0) {
                console.log("We have an alarm, checking if already set");
                callback(null, {"status":"alarms"});
            } else {
                console.log("Event contains no alarm; checking for historic active");
                callback(null, {"status":"no alarms"});
            }
        } else {
            console.log("there's a problem on mongo");
            callback("problem", "status not so good");
        }
    });

    callback(null, {"status":"outside of device find block"});
}

3 个答案:

答案 0 :(得分:20)

你有一个错字:

context.callbackWaitsForEmtpyEventLoop = false;

应该是:

context.callbackWaitsForEmptyEventLoop = false;

以下是documentation关于 callbackWaitsForEmptyEventLoop 行为的说法:

  

callbackWaitsForEmptyEventLoop

     

默认值为true。此属性仅用于修改回调的默认行为。默认情况下,回调将等到Node.js运行时事件循环为空,然后冻结进程并将结果返回给调用者。您可以将此属性设置为false,以便在调用回调后立即请求AWS Lambda冻结进程,即使事件循环中存在事件也是如此。 AWS Lambda将冻结进程,任何状态数据和Node.js事件循环中的事件(当下一次调用Lambda函数并且AWS Lambda选择使用冻结进程时,处理事件循环中的任何剩余事件)。有关回调的详细信息,请参阅Using the Callback Parameter

最小例子:

// Times out due to typo
exports.function1 = (event, context, callback) => {
    setInterval(() => console.log('Long wait'), 100000);
    context.callbackWaitsForEmtpyEventLoop = false;
    callback(null, 'Hello from Lambda');
};

// Returns successfully
exports.function2 = (event, context, callback) => {
    setInterval(() => console.log('Long wait'), 100000);
    context.callbackWaitsForEmptyEventLoop = false;
    callback(null, 'Hello from Lambda');
};

答案 1 :(得分:2)

如果有人像我一样困惑如何将callbackWaitsForEmptyEventLoop添加到新的Alexa项目中,如下所示:

const skillBuilder = Alexa.SkillBuilders.custom();

exports.handler = skillBuilder
  .addRequestHandlers(
      GetNewFactHandler,
      HelpHandler,
      ExitHandler,
      FallbackHandler,
      SessionEndedRequestHandler,
  )
  .addRequestInterceptors(LocalizationInterceptor)
  .addErrorHandlers(ErrorHandler)
  .lambda();

在此处找到示例项目:https://github.com/alexa/skill-sample-nodejs-fact/blob/master/lambda/custom/index.js

此解决方案对我有用:

// create a custom skill builder
const skillBuilder = Alexa.SkillBuilders.custom();

exports.handler = (event, context, callback) => {
  // we need this so that async stuff will work better
  context.callbackWaitsForEmptyEventLoop = false

  // set up the skill with the new context
  return skillBuilder
    .addRequestHandlers(
      GetNewFactHandler,
      HelpHandler,
      ExitHandler,
      FallbackHandler,
      SessionEndedRequestHandler,
    )
    .addRequestInterceptors(LocalizationInterceptor)
    .addErrorHandlers(ErrorHandler)
    .lambda()(event, context, callback);
}

答案 2 :(得分:1)

我正在从android代码触发lambda。 Lambda正在从DynamoDB执行大量数据提升操作,并生成一个JS对象作为响应。我可以在lambda日志中看到生成的对象,但是我的android辅助代码总是超时等待响应。

超时的原因是,同步有效负载的调用有效载荷(请求和响应)限制为6 MB,异步lambda实现的限制为256 KB。在我的情况下,我具有异步实现,并且生成的对象超过256 KB。

没有适当的日志消息可以超出此限制,这使我出轨。参考:https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html

我实现的解决方法是将响应写入S3存储桶中的文本文件,并将其引用作为响应传递给android端,而不是传递实际对象本身。