异步调用 AWS Lambda 和 return 对 API 网关的响应

Invoke AWS Lambda and return response to API Gateway asyncronously

我的用例是这样的,我将有一个以 API 网关结尾的 AWS Lambda 前端。

我的要求是,一旦 Lambda 被调用,它应该 return 一个 200 OK 响应返回到 API 网关,网关将其转发给调用者。 然后 Lambda 应该开始实际处理负载。

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

这可能吗?

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

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

调用第二个异步 Lambda 函数

但是,使用 A​​WS 服务代理 集成而不是 Lambda,无需解决方法 也可以进行异步调用功能整合。

If your API makes only synchronous calls to Lambda functions in the back end, you should use the Lambda Function integration type. [...]

If your API makes asynchronous calls to Lambda functions, you must use the AWS Service Proxy integration type described in this section. The instructions apply to requests for synchronous Lambda function invocations as well. For the asynchronous invocation, you must explicitly add the X-Amz-Invocation-Type:Event header to the integration request.

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

在此处查看有关如何设置对 Lambda 函数的异步调用的答案。这将 return 200 立即发送给客户端,但 Lambda 将自己异步处理。

如果有人感兴趣,这里是您可以用来执行两个 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"
    };

};