AWS Lambda Invoke不执行lambda函数

leo*_*o c 3 mysql amazon-web-services node.js aws-lambda

我创建了4个Lambda函数来处理将写入MySQL表的信息.前三个函数分别只选择,插入和更新MYSQL表记录.

然后我创建了第4个函数来接受记录详细信息作为事件参数的一部分.此函数将首先尝试通过调用第一个lambda函数来选择记录,如果找到它,将使用update lambda函数更新表上的记录.如果找不到,它将调用insert函数来添加记录.我在操作MySQL表的3个函数上使用pool.query.我也使用lambda.invoke从第4个函数调用这三个函数.

通过将记录详细信息作为参数传递,我能够在本地成功测试第4个函数,并且能够成功调用三个Lambda函数并更新mySQL表记录.我遇到的问题是,当我在AWS Lambda中上传函数时,它不会调用这三个函数中的任何一个.我没有在日志中看到任何错误,所以我不知道如何检查问题所在.这是,调用其他函数的代码:

exports.handler = (event, context, callback) => {

var err = null;
var payload = {
        qryString : event.qryString,
        record: event.updaterecord,
        dbConfigPool : event.dbConfigPool
           }

var params = {
  FunctionName: 'getInventory', 
  Payload: JSON.stringify(payload) 
}
console.log(' before invoke ' + JSON.stringify(params) )
lambda.invoke(params, function(err, data) {
console.log(' aftr invoke ' + JSON.stringify(params) )
  if (err) {
    console.log('err ' + err, err.stack); // an error occurred
    event.message = err + ' query error';
  }
  else    { 
      console.log('success' + JSON.stringify(data));   
      console.log(' status code ' + JSON.stringify(data.StatusCode));
      console.log(' Payload ' + JSON.stringify(JSON.parse(data.Payload)));
      var rowsTemp = JSON.parse(data.Payload);
      var rows = rowsTemp.data;
      if (!rowsTemp.recordExist) {
          console.log('insert')
            // Update inventory record only if quantity is not negative
          var newQuantity = 0
      newQuantity = parseFloat(event.updaterecord.quantity);
      if (Math.sign(newQuantity) === 1) {
        var payload = {
                    record: event.updaterecord,
                    dbConfigPool : event.dbConfigPool
                       }

        console.log('insert' + JSON.stringify(payload));
        var params = {
          FunctionName: 'insertInventory', 
          Payload: JSON.stringify(payload) 
        }
            lambda.invoke(params, function(err, data) {
              if (err) console.log(err, err.stack); // an error occurred
              else     console.log(data);           // successful response
            });
        }

  }
  else {
      newQuantity = 0
      newQuantity = parseFloat(event.updaterecord.quantity) + parseFloat(rows[0].quantity);
      if (Math.sign(newQuantity) === 1) {
      event.updaterecord.quantity = newQuantity;
      } else {
        // Set to zero if the result is negative
      event.updaterecord.quantity = 0;
      }
      console.log('value ' + JSON.stringify(newQuantity) + ' updaterecord' + JSON.stringify(event.updaterecord.quantity) );
      var payload = {
                    qryString : event.qryString,
                    record: event.updaterecord,
                    dbConfigPool : event.dbConfigPool
                       }
      console.log('update' + JSON.stringify(payload));
        var params = {
          FunctionName: 'updateInventory', 
          Payload: JSON.stringify(payload) 
        }
        console.log(' before invoke ' + JSON.stringify(params) )
        lambda.invoke(params, function(err, data) {
        console.log(' after invoke ' + JSON.stringify(params) )
          if (err) {
            console.log('err ' + err, err.stack); // an error occurred
            event.message = err + ' query error';
          } else {
              console.log(data);
          } // else
        }); // lambda invoke
  }
  }        // successful response
});

console.log(' end of function');
var completed = true;
context.callbackWaitsForEmptyEventLoop = false; 
callback(null, completed);

}
Run Code Online (Sandbox Code Playgroud)

如果代码很长,请道歉.但我想表明我确实放了一些console.log来监控经过的地方.cloudwatch日志仅显示第一个lambda.invoke之前的第一条消息,然后显示该函数结束的最后一条消息.

我也没有在cloudwatch中看到已调用的三个函数的任何日志条目.

06/17好的,因为我仍然无法完成这项工作,我将代码简化为以下内容:

exports.handler = (event, context, callback) => {

var err = null;
var updatedRecord = false;
var responseDetail = {};
var payload = {
        qryString : event.qryString,
        record: event.updaterecord,
        dbConfigPool : event.dbConfigPool
           }

var params = {
  FunctionName: 'getInventory', 
  Payload: JSON.stringify(payload) 
}
console.log(' before invoke ' + JSON.stringify(params));
lambda.invoke(params, function(err, data) {
  if (err) {
  event.message = err + ' query error';
  callback(err,event.message);
  }
  else    { 

  console.log('success' + JSON.stringify(data));   
  console.log(' status code ' + JSON.stringify(data.StatusCode));
  console.log(' Payload ' + JSON.stringify(JSON.parse(data.Payload)));
  callback(null, data);

  }        // successful response
});

console.log(' end of function');
//    var completed = true;
//    context.callbackWaitsForEmptyEventLoop = false; 
//    callback(null, completed);

}
Run Code Online (Sandbox Code Playgroud)

但是,当我进行测试时,该功能会超时.我还赋予了函数完整的Lambda和RDS访问权限.

bpa*_*lov 6

首先 - 欢迎回调地狱!我稍后会回到这里.

这是一个调用lambda函数的简单代码.

var params = {
  FunctionName: 'LAMBDA_FUNCTION_NAME', /* required */
};
lambda.invoke(params, function(err, data) {
  if (err) {
   console.log(err, err.stack); // an error occurred
  }
  else {
   console.log(data);           // successful response
  }
});
Run Code Online (Sandbox Code Playgroud)

lambda.invoke函数有两个参数(params,function(err,data){..}).第一个是简单的JSON对象.第二个是函数 - 回调函数.当lambda.invoke(您可以认为LAMBDA_FUNCTION_NAME)的执行结束时,此函数将被"回调".如果发生错误,它将"存储"在err变量中,否则返回的数据将存储在数据变量中(这不是正确的解释,但我试图在这里保持简单).

想要一个接一个地调用两个lambda函数会发生什么?

var params1 = {
  FunctionName: 'LAMBDA_FUNCTION_1_NAME', /* required */
};
lambda.invoke(params1, function(err, data) {
  if (err) {
   console.log(err, err.stack); // an error occurred
  }
  else {
   console.log('Lambda function 1 invoked!');
   console.log(data);           // successful response
  }
});
var params2 = {
  FunctionName: 'LAMBDA_FUNCTION_2_NAME', /* required */
};
lambda.invoke(params2, function(err, data) {
  if (err) {
   console.log(err, err.stack); // an error occurred
  }
  else {
   console.log('Lambda function 2 invoked!');
   console.log(data);           // successful response
  }
});
console.log('I am done!');
Run Code Online (Sandbox Code Playgroud)

根据LAMBDA_FUNCTION_1_NAME和LAMBDA_FUNCTION_2_NAME的执行时间,您可以看到不同的输出,例如:

Lambda function 1 invoked!
I am done!
Run Code Online (Sandbox Code Playgroud)

要么

Lambda function 1 invoked!
Lambda function 2 invoked!
I am done!
Run Code Online (Sandbox Code Playgroud)

甚至

Lambda function 1 invoked!
I am done!
Lambda function 2 invoked!
Run Code Online (Sandbox Code Playgroud)

这是因为你正在调用lambda.invoke,之后(不等待)你再次调用lambda.invoke.之后(当然没有等待)以前的函数来结束你正在调用console.log('我完成了!');

你可以通过将每个函数放在上一个函数的回调中来解决这个问题.像这样的东西:

var params1 = {
  FunctionName: 'LAMBDA_FUNCTION_1_NAME', /* required */
};
lambda.invoke(params1, function(err, data) {
  if (err) {
   console.log(err, err.stack); // an error occurred
  }
  else {
   console.log('Lambda function 1 invoked!');
   console.log(data);           // successful response
   var params2 = {
    FunctionName: 'LAMBDA_FUNCTION_2_NAME', /* required */
   };
   lambda.invoke(params2, function(err, data) {
      if (err) {
       console.log(err, err.stack); // an error occurred
      }
      else {
       console.log('Lambda function 2 invoked!');
       console.log(data);           // successful response
       console.log('I am done!');
      }
    });
  }
});
Run Code Online (Sandbox Code Playgroud)

这样你的输出将是:

Lambda function 1 invoked!
Lambda function 2 invoked!
I am done!
Run Code Online (Sandbox Code Playgroud)

但是如果你想一个接一个地调用3个或更多函数,你最终会得到嵌套代码.这是回调地狱.您可以用这种方式重写代码.但在我看来,检查瀑布异步库是个好主意

async.waterfall([
    function(callback) {
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback) {
      // arg1 now equals 'one' and arg2 now equals 'two'
        callback(null, 'three');
    },
    function(arg1, callback) {
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
    // result now equals 'done'
})
Run Code Online (Sandbox Code Playgroud)

伪代码应如下所示:

async.waterfall([
    function(callback1) {
        var params1 = {
            FunctionName: 'LAMBDA_FUNCTION_1_NAME', /* required */
        };
        lambda.invoke(params1, function(err, data) {
            if (err) {
                console.log(err, err.stack); // an error occurred
            }
            else {
                console.log('LAMBDA_FUNCTION_1_NAME finished!');
                callback1(null,data);
            }
        });
    },
    function(result_from_function_1, callback2) {
        console.log(result_from_function_1); // outputs result from LAMBDA_FUNCTION_1_NAME
        var params2 = {
            FunctionName: 'LAMBDA_FUNCTION_2_NAME', /* required */
        };
        lambda.invoke(params2, function(err, data) {
            if (err) {
                console.log(err, err.stack); // an error occurred
            }
            else {
                console.log('LAMBDA_FUNCTION_2_NAME finished!');
                callback2(null,data); 
            }
        });
    },
    function(result_from_function_2, callback3) {
        console.log(result_from_function_2); // outputs result from LAMBDA_FUNCTION_2_NAME
        var params3 = {
            FunctionName: 'LAMBDA_FUNCTION_3_NAME', /* required */
        };
        lambda.invoke(params3, function(err, data) {
            if (err) {
                console.log(err, err.stack); // an error occurred
            }
            else {
                console.log('LAMBDA_FUNCTION_3_NAME finished!');
                callback3(null,data);
            }
        });
    }
], function (err, result) {
    // result now equals LAMBDA_FUNCTION_3_NAME result
})
Run Code Online (Sandbox Code Playgroud)

请注意,所有回调(callback1,callback2和callback3)都只能使用名称"callback".我更改了名字以便更好地理解.


Mic*_*bot 1

想想这有什么作用:

lambda.invoke(params, function(err, data) { ...
Run Code Online (Sandbox Code Playgroud)

它开始“做某事”(恰好调用另一个 lambda 函数的事实实际上并不重要),当“某事”完成时,它会调用 function(),对吧?

但它也会立即返回,并执行下一条语句。

同时,异步事件循环正在处理“某事”。

“下一个声明”是

console.log(' end of function');
Run Code Online (Sandbox Code Playgroud)

然后,你告诉 lambda“嘿,我可能正在进行一些异步操作,但不用担心等待它完成”:

context.callbackWaitsForEmptyEventLoop = false; 
Run Code Online (Sandbox Code Playgroud)

因此,好消息是您的代码正在执行编写的操作……但事实证明这是错误的。

到处都有这两种东西之一......

// an error occurred
// successful response
Run Code Online (Sandbox Code Playgroud)

...这些是您应该调用的地方callback(),而不是在处理程序函数的末尾,您的代码很快就会到达,正如它应该的那样。

context.callbackWaitsForEmptyEventLoop = false;如果您正确断开数据库连接并且您包含的所有模块都表现良好,则不需要使用。虽然这有其目的,但似乎有很多人用它来掩盖微妙的未完成的事情。

或者,对于一个更简洁的解决方案,您在末尾只提到了一次回调,并且您的 function { function { function { 嵌套不会变得如此失控,请使用async-waterfall.