【问题标题】:Serverless Lambda invoking Lambda. Getting no errors but a empty response无服务器 Lambda 调用 Lambda。没有错误,但响应为空
【发布时间】:2019-01-12 05:44:42
【问题描述】:

现在,如果我们想创建一个 lambda 函数来调用另一个函数,我们可以使用 AWS StepFunctions。 但现在我需要支持在 StepFunctions 时间之前编写的生产代码。 出于这个原因,我需要了解它是如何工作的。我试图创建一个非常简单的 lambda,通过 AWS-SDk 调用另一个 lambda 函数。

我有关注 serverless.yml

service: lambdaCallLambda

provider:
  name: aws
  runtime: nodejs6.10

functions:
  hello:
    handler: handler.hello
  funcOne:
    handler: handler.funcOne  
  funcTwo:
    handler: handler.funcTwo

#Must install aws-sdk.  #npm install --save aws-sdk

这是 handler.js:

'use strict';


//https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html
var Lambda = require('aws-sdk/clients/lambda');


module.exports.hello = (event, context, callback) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify({
      message: 'hello',
      input: event,
    }),
  };

  callback(null, response);
};


module.exports.funcOne = (event, context, callback) => { 
  var text='';
  var i = 0;
  for (i = 0; i < 5; i++) {
    text += "The number is " + i + "\n";
  }
  console.log(text);


  //https://docs.aws.amazon.com/general/latest/gr/rande.html
  const lambda = new Lambda({
    region: 'us-east-1'
  });
  console.log('control 3');



  /*

    https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#constructor-property
    To invoke a Lambda function
    This operation invokes a Lambda function

    https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html
    Payload - JSON that you want to provide to your Lambda function as input.

  */
  var params = {
    ClientContext: "lambdaCallLambda", 
    FunctionName: "lambdaCallLambda-dev-funcOne", 
    InvocationType: "Event", 
    LogType: "Tail", 
    Payload: '{"jsonKey2":123}', 
    Qualifier: "1"
  };
  lambda.invoke(params, function(err, data) {
    if (err){
      console.log('control error\n');
      console.log(err, err.stack); // an error occurred
    } 
    else{
      console.log('control OK\n');
      console.log(data);           // successful response
    }     
    /*
    data = {
      FunctionError: "", 
      LogResult: "", 
      Payload: <Binary String>, 
      StatusCode: 123
    }
    */
  });  
};


module.exports.funcTwo = async (event, context) => { 
  return 2;
  //return '{"funcTwo":20000}';
  //console.log("funcTwo = " + event);
};  

部署sls deploy 并调用funcOne 后,我得到这2 个输出:

本地: sls invoke local --function funcOne

Serverless: INVOKING INVOKE
The number is 0
The number is 1
The number is 2
The number is 3
The number is 4

control 3
control OK

{ StatusCode: 202, Payload: '' }

在 AWS 中远程调用: sls invoke --function funcOne

{
    "errorMessage": "Unexpected token (",
    "errorType": "SyntaxError",
    "stackTrace": [
        "                               ^",
        "SyntaxError: Unexpected token (",
        "createScript (vm.js:56:10)",
        "Object.runInThisContext (vm.js:97:10)",
        "Module._compile (module.js:542:28)",
        "Object.Module._extensions..js (module.js:579:10)",
        "Module.load (module.js:487:32)",
        "tryModuleLoad (module.js:446:12)",
        "Function.Module._load (module.js:438:3)",
        "Module.require (module.js:497:17)",
        "require (internal/module.js:20:19)"
    ]
}

  Error --------------------------------------------------

  Invoked function failed

     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com

  Your Environment Information -----------------------------
     OS:                     linux
     Node Version:           8.11.3
     Serverless Version:     1.29.2

有人知道帽子在这里发生吗?特别是对于我没有任何错误的第一种情况。 这就是我得到的from the documentation

Parameters:

err (Error) — the error object returned from the request. Set to null if the request is successful.
data (Object) — the de-serialized data returned from the request. Set to null if a request error occurs. The data object has the following properties:
Status — (Integer)
It will be 202 upon success.

更新

根据 Eduardo Díaz 的建议 - 我已将 lambda.invoke 更改为:

lambda.invoke({
    FunctionName: 'lambdaCallLambda-dev-funcOne',
    Payload: JSON.stringify(event, null, 2)
  }, function(error, data) {
    if (error) {
      console.log('control ErrorFoncOne\n');
      context.done('error', error);
    }
    if(data.Payload){
     console.log('control SuccessFoncOne\n'); 
     context.succeed(data)
    }
  });

这就是我在本地和远程得到的:

{
    "errorMessage": "Unexpected token (",
    "errorType": "SyntaxError",
    "stackTrace": [
        "Module.load (module.js:487:32)",
        "tryModuleLoad (module.js:446:12)",
        "Function.Module._load (module.js:438:3)",
        "Module.require (module.js:497:17)",
        "require (internal/module.js:20:19)"
    ]
}

这是一个语法错误。某处有一个“(”。 我发现另一个开发人员出现了同样的错误here

注意:

CloudWatch 中没有错误日志

【问题讨论】:

    标签: amazon-web-services aws-lambda serverless-framework


    【解决方案1】:

    尝试在有效载荷中发送事件:

    lambda.invoke({
      FunctionName: 'name_lambda_function',
      Payload: JSON.stringify(event, null, 2)
    }, function(error, data) {
      if (error) {
        context.done('error', error);
      }
      if(data.Payload){
       context.succeed(data.Payload)
      }
    });
    

    【讨论】:

    • 嘿 Eduardo,我刚刚运行了您的更改。我在本地遇到了与远程相同的错误。我认为现在更好。至少我可以看到双方的错误。投诉是关于某处的“(”。我已经查看了代码,我发现它在哪里。
    【解决方案2】:

    我强烈怀疑这个问题源于您对funcTwo 的处理程序签名:

    module.exports.funcTwo = async (event, context) => { 
    

    NodeJS 6.10 不支持async/await。无论出于何种原因,Node 总是在async 令牌之后抱怨令牌。如果不使用粗箭头函数:

    module.exports.funcTwo = async function(event, context) {
    

    节点会抱怨:Unexpected token function

    选项

    • 改为将函数部署到 NodeJS 8.10。
    • 去掉处理程序签名中的async 关键字。
    • 使用构建工具(如 serverless-webpack)将函数转换为 ES6(或更低版本)。

    注意:如果你坚持使用 6.10 运行时,我想你会想要做类似context.succeed(2);callback(null, 2);,而不是return 2;。只需使用 return 语句确实似乎在 8.10 上有效。

    【讨论】:

      【解决方案3】:

      我找到了问题。我们在 lamdda.invoke 方法的 playload 中需要 JSON.stringfy。不需要额外的参数。根据文档,只有 JSON。

      lambda.invoke({
            FunctionName: 'lambdaCallLambda-dev-funcTwo',
            Payload: JSON.stringify({"jsonKey2":i})
      ...
      

      来自AWS documentation for playload 我们有:

      Payload
      JSON that you want to provide to your Lambda function as input.
      

      注意:

      函数前面的async

      lambda.invoke({
            FunctionName: 'lambdaCallLambda-dev-funcTwo',
            Payload: JSON.stringify({"jsonKey2":i})
          }, async function(error, data) { ...
      

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

      给我这个输出:

      Loop nb=1
      
      Loop nb=2
      
      Loop nb=3
      
      Loop nb=4
      
      Loop nb=5
      
      {"message":"hello from funcTwo","event":{"jsonKey2":3}}
      {"message":"hello from funcTwo","event":{"jsonKey2":2}}
      {"message":"hello from funcTwo","event":{"jsonKey2":1}}
      {"message":"hello from funcTwo","event":{"jsonKey2":5}}
      {"message":"hello from funcTwo","event":{"jsonKey2":4}}
      

      虽然没有 async 给了我:

      Loop nb=1
      
      Loop nb=2
      
      Loop nb=3
      
      Loop nb=4
      
      Loop nb=5
      
      {"message":"hello from funcTwo","event":{"jsonKey2":1}}
      {"message":"hello from funcTwo","event":{"jsonKey2":2}}
      {"message":"hello from funcTwo","event":{"jsonKey2":3}}
      {"message":"hello from funcTwo","event":{"jsonKey2":4}}
      {"message":"hello from funcTwo","event":{"jsonKey2":5}}
      

      我将分享handle.js 代码以防其他人需要它:

      'use strict';
      
      
      //https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html
      var Lambda = require('aws-sdk/clients/lambda');
      
      
      module.exports.hello = (event, context, callback) => {
        const response = {
          statusCode: 200,
          body: JSON.stringify({
            message: 'hello',
            input: event,
          }),
        };
      
        callback(null, response);
      };
      
      /*
      
          https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#constructor-property
          To invoke a Lambda function
          This operation invokes a Lambda function
      
          https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html
          Payload - JSON that you want to provide to your Lambda function as input.
      
          Serverless Framework: Lambdas Invoking Lambdas
          https://lorenstewart.me/2017/10/02/serverless-framework-lambdas-invoking-lambdas/
      
          How to escape async/await hell
          https://medium.freecodecamp.org/avoiding-the-async-await-hell-c77a0fb71c4c
      
          Iterating a Loop Using Lambda
          https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-create-iterate-pattern-section.html
      
      
          AWS Lambda “Process exited before completing request”
          https://stackoverflow.com/questions/31627950/aws-lambda-process-exited-before-completing-request
      
      
          Class: AWS.Lambda
          https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#constructor-property
          Invoke
          https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestSyntax
      
      
          Programming Model(Node.js)
          https://docs.aws.amazon.com/lambda/latest/dg/programming-model.html
      
      
          AWS Lambda Examples
          https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/lambda-examples.html
      
        */
      
      
      
      //The event is a file inserted in S3. This function funcOne reads the file and loop trough all quantities of products.
      //Invoking a lamda function funcTwo for each process in the loop.
      module.exports.funcOne = (event, context, callback) => { 
      
        //https://docs.aws.amazon.com/general/latest/gr/rande.html
        const lambda = new Lambda({
          region: 'us-east-1'
        });
      
        //Loop
        //nbProducts = loop trough the products JSON list in S3    
        var nbProducts=5;  
        for (let i = 1; i <= nbProducts; i++) {
          console.log('Loop nb='+i+'\n');
      
        lambda.invoke({
            FunctionName: 'lambdaCallLambda-dev-funcTwo',
            Payload: JSON.stringify({"jsonKey2":i})
          }, async function(error, data) {
            if (error) {
              //console.log('control ErrorFoncOne\n');
              context.done('error', error);
            }
            if(data.Payload){
             //console.log('control SuccessFoncOne\n'); 
             console.log(data.Payload);
             //context.succeed(data)
            }
          });
        }  
      };
      
      
      module.exports.funcTwo = async(event, context, callback) => {
         callback(null, { message: 'hello from funcTwo', event });
      };
      

      【讨论】:

        【解决方案4】:

        只需更改一行即可 改变参数

            'use strict';
        
        
           //https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html
            var Lambda = require('aws-sdk/clients/lambda');
        
        
            module.exports.hello = (event, context, callback) => {
             const response = {
             statusCode: 200,
             body: JSON.stringify({
             message: 'hello',
             input: event,
              }),
             };
        
            callback(null, response);
            };
        
        
           module.exports.funcOne = (event, context, callback) => { 
            var text='';
            var i = 0;
            for (i = 0; i < 5; i++) {
            text += "The number is " + i + "\n";
             }
             console.log(text);
        
        
              //https://docs.aws.amazon.com/general/latest/gr/rande.html
             const lambda = new Lambda({
             region: 'us-east-1'
              });
              console.log('control 3');
        
                     
                 var params = {
                  ClientContext: "lambdaCallLambda", 
                  FunctionName: "lambdaCallLambda-dev-funcOne", 
                  InvocationType: "RequestResponse", /* changed this line from 
                                         "Event" to "RequestResponse"*/
                  LogType: "Tail", 
                  Payload: '{"jsonKey2":123}', 
                  Qualifier: "1"
                   };
               lambda.invoke(params, function(err, data) {
                if (err){
                console.log('control error\n');
                console.log(err, err.stack); // an error occurred
                } 
              else{
                console.log('control OK\n');
                console.log(data);           // successful response
                }     
               /*
               data = {
               FunctionError: "", 
               LogResult: "", 
               Payload: <Binary String>, 
               StatusCode: 123
                  }
                   */
               });  
              };
        
        
            module.exports.funcTwo = async (event, context) => { 
             return 2;
            //return '{"funcTwo":20000}';
            //console.log("funcTwo = " + event);
             };  
        

        【讨论】:

          猜你喜欢
          • 2018-03-19
          • 2018-10-01
          • 2018-09-17
          • 2020-10-13
          • 2018-05-16
          • 1970-01-01
          • 2020-04-21
          • 2020-02-12
          • 2021-01-20
          相关资源
          最近更新 更多