【问题标题】:Invoke AWS Lambda and return response to API Gateway asyncronously调用 AWS Lambda 并向 API Gateway 异步返回响应
【发布时间】:2017-04-27 09:45:27
【问题描述】:

我的用例是,我将拥有一个带有 API 网关的 AWS Lambda 前端。

我的要求是,一旦调用 Lambda,它应该向 API Gateway 返回 200 OK 响应,API Gateway 将其转发给调用者。 然后 Lambda 应该开始实际处理有效负载。

原因是 API Gateway 调用者服务期望在 10 秒内得到响应,否则会超时。所以我想在开始处理之前给出响应。

这可能吗?

【问题讨论】:

  • 我们之前好像有过这个问题,但我没有找到合适的重复问题。

标签: amazon-web-services aws-lambda aws-api-gateway


【解决方案1】:

使用 API Gateway 的“Lambda 函数”集成类型,您无法使用单个 Lambda 函数执行此操作 - 该接口专门设计为同步。如果您想使用 Lambda 函数集成类型,解决方法是让网关调用的同步 Lambda 函数通过 Lambda API 调用第二个异步 Lambda 函数。

但是,使用 AWS 服务代理 集成而不是 Lambda 函数 集成,可以在没有解决方法的情况下进行异步调用

如果您的 API 仅在后端对 Lambda 函数进行同步调用,则应使用 Lambda 函数集成类型。 [...]

如果您的 API 对 Lambda 函数进行异步调用,您必须使用本节中描述的 AWS Service Proxy 集成类型。这些说明也适用于同步 Lambda 函数调用的请求。对于异步调用,您必须将X-Amz-Invocation-Type:Event 标头显式添加到集成请求中。

http://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-lambda.html

【讨论】:

  • 我们如何添加这个标题?我们必须在“HTTP Header”下添加它吗?在集成请求中?似乎我只能添加标头映射,但不能添加硬编码的标头值。谢谢。
  • 好的,它允许单引号中的标题值,但不允许双引号。那是我挣扎的地方。如此糟糕的用户体验。
  • @vangap 'STATIC_VALUE'STATIC_VALUE 是字符串文字,必须用一对单引号括起来。” docs.aws.amazon.com/apigateway/latest/developerguide/…
  • 谢谢迈克尔,希望我早点看到 :)
【解决方案2】:

是的,只需创建两个 Lambda 函数。第一个 Lambda 函数将由 API Gateway 调用,并将简单地调用第二个 Lambda 函数,然后立即成功返回,以便 API Gateway 可以向客户端响应 HTTP 200。然后,第二个 Lambda 函数将需要完成所需的时间。

【讨论】:

  • 或者,可以使用队列 (SQS)。您可以将 API Gateway 直接连接到 SQS 队列或使用 Lambda 函数。在任何情况下,您都可以按照自己喜欢的速度处理消息。
  • 是的 2 lambda 方法绝对可以完成。但是我们可以用一个 lambda 来实现吗
【解决方案3】:

如果有人感兴趣,这里是您可以用来执行两个 lambda 方法的代码。下面的代码是您应该设置的第一个 lambda,然后它将调用第二个运行时间更长的 lambda。执行时间不到一秒。

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

/**
 * Note: Step Functions, which are called out in many answers online, do NOT actually work in this case.  The reason
 * being that if you use Sequential or even Parallel steps they both require everything to complete before a response
 * is sent.  That means that this one will execute quickly but Step Functions will still wait on the other one to
 * complete, thus defeating the purpose.
 *
 * @param {Object} event The Event from Lambda
 */
exports.handler = async (event) => {
    let params = {
      FunctionName: "<YOUR FUNCTION NAME OR ARN>",
      InvocationType: "Event",  // <--- This is KEY as it tells Lambda to start execution but immediately return / not wait.
      Payload: JSON.stringify( event )
    };

    // we have to wait for it to at least be submitted. Otherwise Lambda runs too fast and will return before
    // the Lambda can be submitted to the backend queue for execution
    await new Promise((resolve, reject) => {
        Lambda.invoke(params, function(err, data) {
            if (err) {
                reject(err, err.stack);
            }
            else {
                resolve('Lambda invoked: '+data) ;
            }
        });
    });

    // Always return 200 not matter what
    return {
        statusCode : 200,
        body: "Event Handled"
    };

};

【讨论】:

    【解决方案4】:

    在此处查看有关如何为 Lambda 函数设置异步调用的答案。这将立即向客户端返回 200,但 Lambda 将自行异步处理。

    https://stackoverflow.com/a/40982649/5679071

    【讨论】:

      猜你喜欢
      • 2019-08-03
      • 1970-01-01
      • 2015-10-21
      • 2017-10-04
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 2015-12-04
      • 2017-04-19
      相关资源
      最近更新 更多