如何使用无服务器框架从另一个 lambda 异步调用 lambda

Posted

技术标签:

【中文标题】如何使用无服务器框架从另一个 lambda 异步调用 lambda【英文标题】:How to invoke lambda asynchronously from another lambda using serverless framework 【发布时间】:2020-10-15 09:19:18 【问题描述】:

我正在尝试在无服务器框架中构建一个架构,其中一个 Lambda 使用 Node.js AWS 开发工具包异步调用另一个 Lambda。我知道在异步调用时,调用 Lambda 不会等待被调用的 Lambda 运行并响应,而是会从 AWS 获得带有调用本身状态的响应。

根据我的阅读,异步调用 Lambda 的方法是在参数中使用带有 InvocationType: 'Event' 的 Lambda invoke() 方法(而不是使用 InvocationType: 'RequestResponse' 进行同步调用)。但是,我设置为InvocationType 似乎并不重要;第二个 Lambda 始终完整运行并将其响应返回给第一个,就像我设置了 InvocationType: 'RequestResponse'

在我的serverless.yml 文件中,我有:

functions:
  receive_deltas:
    handler: src/record/delta_lambdas.receive
    vpc: $self:custom.vpc
    events:
      - http:
          method: post
          path: v1/deltas
  
  process_deltas:
    handler: src/record/delta_lambdas.process
    vpc: $self:custom.vpc

在我的 TypeScript 处理程序中,我有:

import  Lambda  from 'aws-sdk';

export const receive = async (event) => 
  const  recordIds  = JSON.parse(event.body);

  const lambda = new Lambda(
    region: 'us-west-2',
    endpoint: 'http://localhost:3003',
  );

  const params = 
    FunctionName: 'orgconfig-dev-process_deltas',
    InvocationType: 'Event',
    Payload: JSON.stringify( recordIds ),
  ;

  lambda.invoke(params, (err, data) => 
    if (err) 
      console.log(err);
      return failureResponse(err);
     else 
      return parseResponse(data);
    
  );
;

export const process = async (event) => 
  console.log('running process lambda');

  // process a bunch of stuff

  console.log('finished processing');
;

第一个 Lambda 总是等待第二个 Lambda 完整运行,并最终得到 StatusCode: 200, Payload: '' 的响应。我期待一个成功的异步调用返回一个带有StatusCode: 202 的即时响应。

我错过了什么?

【问题讨论】:

【参考方案1】:

使用无服务器离线和异步 Lambda 调用为他们工作的配置,可能值得在这里发布给未来的国际用户

以防万一有人在寻找工作配置...

对 serverless.yml 中的两个(调用者和被调用的)函数尝试 async: true

InvocationType 应该是 lambda.invoke 参数中的“Event”

iam 角色声明lambda:InvokeAsync

FunctionName 用于离线调用应该采用 serviceName-stage-functionName 格式,所以它看起来像:

functions:
  invoker:
  handler: ...your-handler
   environment:
     your_Ref_to_offlineLamName: "$self:service-$opt:stage, self:provider.stage-invoked"
     events:
      - http:
          method: get
          path: ...yourpath
          async: true
   invoked:
     handler: ...somehandler
     events:
      - http:
          method: post
          path: ...somepath
          async: true

处理程序

let param = 
      FunctionName: process.env.IS_OFFLINE == "true" ? process.env.your_Ref_to_offlineLamName : "whatever",
      InvocationType: "Event",
      Payload: JSON.stringify(test:"TESTTEST")
    ;
   lambda.invoke(param).promise()

在 node15 中测试。 (基于https://www.serverless.com/plugins/serverless-offline#usage-with-invoke)

【讨论】:

【参考方案2】:

我似乎缺少的是,Serverless Offline 插件——或者至少是我的配置——没有以这种方式模拟异步 lambda 调用。 (请注意,在我的 Lambda 构造函数中,我有一个 localhost 端点,表明它处于离线状态。)一旦我部署到 AWS 实例,它就可以完美运行。

如果有人有适合他们使用无服务器离线和异步 Lambda 调用的配置,则可能值得在此处发布以供未来的国际用户使用。

【讨论】:

以上是关于如何使用无服务器框架从另一个 lambda 异步调用 lambda的主要内容,如果未能解决你的问题,请参考以下文章

AWS Lambda 上的 Nestjs(无服务器框架)|如何访问事件参数?

如何在 serverless.yml 中配置 eventbridge 规则(使用无服务器框架)以在特定时间调用 lambda

AWS Lambda 中的 Amazon S3 waitFor()

如何从 AWS Lambda 函数 + 无服务器框架的 URL 中删除阶段?

如何避免通过重新映射无服务器框架从 Lambda 传递回 API 网关的标头?

如何在无服务器框架或 AWS lambda 中启用节点 js 的实验性功能