调用AWS Lambda并异步返回API网关响应

时间:2016-12-12 13:47:31

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

我的用例是这样的,我将使用API​​网关结束AWS Lambda前端。

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

原因是API网关调用程序服务需要在10秒内响应,否则会超时。所以我想在开始处理之前给出响应。

这可能吗?

4 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:4)

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

但是,使用 AWS Service Proxy 集成而不是 Lambda Function 集成,可以在没有解决方法的情况下进行异步调用

  

如果您的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

答案 2 :(得分:0)

在此处查看如何设置异步调用到Lambda函数的答案。这将立即返回200给客户端,但Lambda将异步处理它自己。

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

答案 3 :(得分:0)

如果有人感兴趣,可以使用以下代码来执行两种lambdas方法。下面的代码是您应设置的第一个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"
    };

};