Api 网关:用于 Lambda 集成的 AWS 子域

Api Gateway: AWS Subdomain for Lambda Integration

我正在尝试将我的 lambda 函数与 API 网关集成,该函数必须 运行 异步,因为它花费的时间太长。我相信我必须选择 "AWS Service" 并指定 Lambda,而不是选择 "Lambda" 集成类型。 (例如 this and this 似乎暗示了这一点。)

但是,当我尝试将 AWS 子域设置为我的 Lambda 函数的 ARN 时,我收到消息 "AWS ARN for integration must contain path or action"。如果我将子域设置为我的 Lambda 函数的名称,则在尝试部署时我会得到 "AWS ARN for integration contains invalid path".

适合此类集成的 AWS 子域是什么?

请注意,我也可以采纳 的建议并设置 Kinesis 流,但这对于我的简单用例来说似乎太过分了。如果那是解决我问题的正确方法,欢迎尝试。

编辑:包括屏幕截图

编辑:请参阅下面的评论以获得不完整的解决方案。

所以设置起来很烦人,但是有两种方法:

  1. 设置常规 Lambda 集成,然后添加此处描述的 InvocationType header http://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html。该值应为 'Event'。

    • 这很烦人,因为当您将 Lambda 函数作为集成类型时,控制台不允许您添加 headers。您必须使用 SDK 或 CLI,或者使用可以轻松添加 header 的 Swagger。
  2. 将整个事情设置为控制台中的 AWS 集成(这就是您在问题中所做的),这样您就可以在控制台中设置 InvocationType header

    • 将子域留空
    • "Use path override" 并将其设置为 /2015-03-31/functions/<FunctionARN>/invocations,其中 <FunctionARN> 是您的 lambda 函数的完整 ARN
    • HTTP 方法是 POST
    • 添加值为 'Event'
    • 的静态 header X-Amz-Invocation-Type

http://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html

我所做的另一个选择是仍然使用 Lambda 配置并使用两个 lambda。第一个(下面的代码)在一秒钟内运行,returns 立即运行。但是,它真正做的是触发第二个 lambda(您的主要 lambda),它可以作为 Event 长 运行(最多 15 分钟限制)。我发现这更直接。


/**
 * 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"
    };

};