【问题标题】:Aws Lambda does not invoke the child Lambda FunctionAws Lambda 不调用子 Lambda 函数
【发布时间】:2021-03-10 16:48:30
【问题描述】:

我创建了一个 lambda 函数来从 sql 表中读取数据、操作数据并调用另一个 lambda 函数将结果通过电子邮件发送给多方。

var aws = require("aws-sdk");
var sql = require("mssql");
var lambda = new aws.Lambda({ region: "eu-central-1" });

exports.handler = async (event, context, callback) => {
    let dataQuery = sqlQuery(); /*prepare the query*/
   
    let result = {};
    try{
        result = await getData(dataQuery); /*fetch data*/
    }catch (err){
        console.log(err);
        throw new Error(err);
    }
    const data = prepareRes(result.recordsets[0][0])
   
    const emails = processData(JSON.parse(data));
    const params ={
        FunctionName: "testSesSendEmail",
        InvocationType: "Event",
        Payload: '<h2>Some Sample</h2>',
        LogType        : 'None',
        };
        
    
    return emails.map(async email => {
        console.log(email.emailAddr) /* everything works fine */
        
       lambda.invoke(params, function(err,data){
           console.log('callback entered')
           if (err) {console.log(err, err.stack)}
           else {
               console.log('Lambda function 1 invoked!');
                console.log(data); 
           }
       })
       
    })
    
   
     
    
   
};

出于测试目的,我已经用虚拟数据填充了有效负载。 子 lambda 似乎没有被调用。我已经设置了必要的 Iam 策略和角色,并将它们附加到父函数。 想不通怎么回事。 感谢您的帮助。

【问题讨论】:

  • 您的 lambda 是否在 VPC 内运行?
  • @jellycsc 是的。我已将这两个功能放在同一个 VPC 中,但无济于事
  • 好的,当它尝试调用第二个 lambda 时,您的 lambda 超时了吗?
  • 不,它没有。但它根本不会在 lambda 回调中记录控制台消息。
  • 在你的问题中包含日志输出怎么样?

标签: amazon-web-services aws-lambda


【解决方案1】:

您期望emails.map(...) 会返回什么?这将是一个未定义值的数组,与emails 数组的长度相同,因为您的内部回调函数不返回值。取而代之的是,您需要它返回一组承诺。

此外,来自异步 Lambda 处理程序的返回值应该是单个 Promise,而不是 Promise 数组,因此您需要将该 Promise 数组折叠为单个 Promise。执行此操作的典型方法是使用Promise.all(),但请注意other options

试试这样的:

const promises = emails.map(email => lambda.invoke(params).promise());  
return Promise.all(promises);

请注意,此代码(以及您的代码)实际上并没有以任何有意义的方式使用 email 参数,因此您需要修复它。

另外,改变这个:

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

到这里:

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

不要在异步 Lambda 处理程序中使用(甚至提供)回调。

另外,请注意,由于InvocationType='Event',您正在异步调用子 Lambda。这可能是您想要的,但只是想检查一下。

【讨论】:

  • 我按照您的建议更改了代码,但我现在收到 TypeError: Promise.All is not a function。子函数仍未被调用。我没有在逻辑中使用 email 参数的原因是为了简化。一旦调用运行,我会将其放入逻辑中。
  • 问题是我把两个 lambdas 都放在了一个 vpc 中。父级需要在 vpc 中才能进行数据库查询。但是当我将两个 lambdas 移出 vpc 时,它们工作正常(数据库查询除外)。我如何配置 vpc 才能正常工作?
  • 错字,抱歉。它是Promise.all(...),但希望快速搜索可以帮助您解决这个问题。调用另一个 Lambda 的 Lambda 需要具有到 AWS Lambda 服务端点的网络路由。在 VPC 中运行时,这意味着 a) 私有子网具有到公有子网中 NAT 的默认路由,或者 b) 您使用 VPC 终端节点访问 Lambda 服务。 Lambda 应该在私有子网中运行。这与您的编码问题不同。有关于如何通过快速搜索执行此操作的可用文档。