【问题标题】:invoke aws lambda from another lambda asynchronously从另一个 lambda 异步调用 aws lambda
【发布时间】:2016-12-31 18:48:18
【问题描述】:

我需要从另一个 lambda 异步调用 aws lambda。我有一个用于同步调用的工作代码。

exports.handler = (event, context, callback) => {
    var aws = require('aws-sdk');
    var lambda = new aws.Lambda({
        region: 'myregion' //change to your region
    });
    console.log("lambda invoke started");
    lambda.invoke({
        FunctionName: 'testLambda',
        Payload: JSON.stringify(event, null, 2) // pass params
    }, function (error, data) {
        if (error) {
            console.log("error");
            callback(null, 'hello world');
        }
        else {
            console.log("lambda invoke end");
            callback(null, 'hello world');
        }
    });
}

但就我而言,“testLambda”是一个耗时的函数。因为我需要在调用“testLambda”函数后退出。然后代码像这样更新

exports.handler = (event, context, callback) => {
    var aws = require('aws-sdk');
    var lambda = new aws.Lambda({
        region: 'myregion' //change to your region
    });
    console.log("lambda invoke started");
    lambda.invoke({
        FunctionName: 'testLambda',
        Payload: JSON.stringify(event, null, 2) // pass params
    });
    console.log("lambda invoke end");
    callback(null, 'hello world');
}

它正确返回消息。但是我的“testLambda”函数没有被调用(没有为测试 lambda 生成云监视日志)。与此代码相关的问题是什么。

【问题讨论】:

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


    【解决方案1】:

    根据the Lambda invoke() documentation,您将看到默认情况下使用RequestResponse 调用类型调用Lambda 函数。要异步调用函数,您需要指定 Event 调用类型,如下所示:

    lambda.invoke({
        FunctionName: 'testLambda',
        InvocationType: 'Event',
        Payload: JSON.stringify(event, null, 2)
    },function(err,data){});
    

    【讨论】:

      【解决方案2】:

      我正在使用 AWS Lambda 中当前最新的 node.js 8.10 版本。
      在我使用 async/await 机制之前,第二个 lambda 没有执行(并且从未调用过回调函数)。
      所以处理函数必须是异步的,并且“lambda.invoke”调用用Promise包装。

      这是我的工作代码:

      function invokeLambda2(payload) {
          const params = {
              FunctionName: 'TestLambda2',
              InvocationType: 'Event',
              Payload: JSON.stringify(payload)
          };
      
          return new Promise((resolve, reject) => {
      
              lambda.invoke(params, (err,data) => {
                  if (err) {
                      console.log(err, err.stack);
                      reject(err);
                  }
                  else {
                      console.log(data);
                      resolve(data);
                  }
              });     
          });
      }
      
      
      exports.handler = async (event, context) => {
          const payload = {
              'message': 'hello from lambda1'
          };
          await invokeLambda2(payload);
          context.done();
      };
      

      请注意,处理程序不会等待第二个 lambda 退出,而是会触发它并调用回调函数。

      您也可以从处理程序中返回 Promise,不必将 await 与第二个函数一起使用。

      在使用 Promises 和 async/await 时不需要任何导入,除了:

      const AWS = require('aws-sdk');
      const lambda = new AWS.Lambda();
      

      【讨论】:

      • 当您收到 AccessDeniedException 时,不要忘记将“AWSLambdaRole”策略添加到您的 IAM 角色。 {“版本”:“2012-10-17”,“声明”:[{“效果”:“允许”,“操作”:[“lambda:InvokeFunction”],“资源”:[“*”]}] }
      • 工作就像一个魅力,只是一个侧面说明异步调用的良好响应是:INFO { StatusCode: 202, Payload: '' }(来自 CloudWatch Logs)
      • 工作了 2 天以使 lambda.invoke 正常工作,我的上帝终于找到了这个像魅力一样工作的解决方案。感谢您发布此解决方案。
      • 我认为这段代码不是异步的。如果您正在等待调用Lambda2(有效负载);然后你正在以同步方式执行第二个 lambda。我错过了什么吗? @ronginat
      • 嗯,它是“异步”的,就像你用Promise 包装的所有其他代码一样。请注意,第二个 lambda 的调用与其实际执行是分开的。因此,它无需等待源 lambda 即可执行。如果您的主处理程序是异步的并且您希望等待以异步方式调用另一个 lambda,则此答案是相关的。
      【解决方案3】:

      这就是我在 Express.js 中使用的方式

      
      var express = require("express");
      var router = express.Router();
      
      const asyncMiddleware = fn =>
        (req, res, next) => {
          Promise.resolve(fn(req, res, next))
            .catch(next);
        };
      
      const invokeLambda = async (params) => {
        const data = await lambda.invoke(params).promise();
        return JSON.parse(data.Payload);
      }
      
      
      router.get('/test', asyncMiddleware(async (req, res, next) => {
        const params = {
          FunctionName: SOMETHING_LAMBDA_ARN,
          Payload: JSON.stringify(req.body)
        };
        const result = await invokeLambda(params);
        res.send(result);
      }));
      
      

      【讨论】:

        【解决方案4】:

        我想要一个与上述类似的解决方案。虽然现在在使用多个 lambda 函数而不是 lambda.invoke 时建议使用阶跃函数,但我使用以下代码 sn-p 从我的基本 lambda 函数异步调用另外两个 lambda 函数。

        var AWS = require('aws-sdk');
        AWS.config.region = 'ap-southeast-1';
        var lambda = new AWS.Lambda();
        
        exports.handler = async(event) => {
           await invokeLambda(event);
           
           const response = {
                statusCode: 200,
                body: JSON.stringify('success'),
           };
           
           return response;
        };
        
        //Invoke Multiple Lambda functions
          async function invokeLambda(event) {
            const function1 = {
                FunctionName: 'dev-test-async-lambda-1',
                InvocationType: 'Event',
                Payload: JSON.stringify(event)
            };
        
            const function2 = {
                FunctionName: 'dev-test-async-lambda-2',
                InvocationType: 'Event',
                Payload: JSON.stringify(event)
            };
            
            await lambda.invoke(function1).promise();
            await lambda.invoke(function2).promise();
        
        }
        
                
        

        如果我可以改进,请告诉我。

        【讨论】:

          【解决方案5】:

          参考Ronginat's answer,您可以直接使用lambda.invoke().promise() 并执行以下操作,而不是将lambda.invoke() 包装在Promise 中:(在Node.js 12.x 中测试)

          exports.handler = async (event) => {
          
              const payload = 'hello from lambda 1';
          
              const params = {
                  FunctionName: 'lambda2',
                  InvocationType: 'Event',
                  Payload: JSON.stringify(payload),
              };
          
              const LambdaPromise = (params) => lambda.invoke(params).promise();
          
              const responseFromLambda2 = await LambdaPromise(params);
          
              return responseFromLambda2; //this should return {StatusCode: 202, Payload: ''}
          };
          

          【讨论】:

            猜你喜欢
            • 2020-03-04
            • 2021-12-30
            • 1970-01-01
            • 2021-11-04
            • 2018-08-21
            • 2018-06-09
            • 1970-01-01
            • 2021-06-04
            • 2018-01-19
            相关资源
            最近更新 更多