I'm using API Gateway-to-Lambda for a few micro-services but in at least one case the service will take 20-30 seconds to complete so in cases like this I'd like to pass back an immediate response to the client, something like:
status: 200
message: {
progressId: 1234
}
and then allow the Lambda Function to continue on (and periodically updating the "processId" somewhere that is accessible to a client. The problem is that if you call context.succeed(), context.fail(), or context.done() that apparently stops the lambda function from further execution and yet it's the only way I know to flush the stdout buffer back to the API Gateway.
This has led me to a second approach which I haven't yet try to tackle (and for simplicity sake would love to avoid) which involves API Gateway calling a "Responder" Lambda function that then asynchronously fires off the Microservice and then immediately responds to the API Gateway.
I've tried to illustrate these two options in sketch format below. I'd love to hear how anyone's been able to solve this problem.
Currently API Gateway requires that the AWS Lambda integration is synchronous. If you desire asynchronous invocation of your Lambda function, you have 2 options:
Invoking the Lambda asynchrously, either with an AWS integration calling InvokeAsync on Lambda, or using an intermediate service such as SNS or Kinesis to trigger the Lambda function.
You're #2 diagram, using a synchronous Lambda invoke to initiate the asynchronous invoke.
As of Apr/2016 is it is possible to create async Lambda execution through API Gateway by using AWS Service Proxy. See http://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-lambda.html
You can send the X-Amz-Invocation-Type header, it supports async calls through the Event value
You can optionally request asynchronous execution by specifying Event as the InvocationType
http://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestSyntax
Also, if you can't send it via your micro-service, you can configure this header to be passed by default through the Method Execution -> Integration Request -> HTTP Headers in your API Gateway Resource
This worked for me on a micro-service -> API Gateway -> Lambda scenario, like the mentioned on the question.
Related
I setup my lambda in AWS in the following way:
There is an API Gateway trigger which triggers a Lambda, which in turn is supposed to write to SQS.
The last part doesn't happen. From what I've read, this is because API Gateway invokes lambdas synchronously by default since calling it async-ly sacrifices the ability to return a response from the lambda.
I have also read that nonetheless, it is possible to configure API Gateway to call lambas async: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-integration-async.html
However, it is unclear how to do this when the API Gateway is created by Lambda, as is the case with triggers. There is no clear way of adding additional headers to them.
Is it possible make it do an async invocation?
After digging into it, it seems that API Gateway does not (yet) support async invocations for lambdas in any way for HTTP APIs, it is possible REST APIs.
Step 1: Create a trigger using the REST configuration
Step 2: Disable proxy integration
Async is explicitly not supported for proxies.
Step 3: Add magic header to make lambda async
Step 4: Confirm
To confirm if it worked, look into your destination (in my case SQS) to confirm.
Additionally, your API (when called via API Gateway) should now return an empty page.
I have created a micro service architecture which flows as follows:
Api call -> Api gateway -> Eventbridge -> SNS -> Lambda
The reason for this is to use SNS instead of SQS to decouple applications for true serverless compute without the need for lambda to continuously poll sqs, pub sub over push poll.
The trouble is that although the execution is fine and the lambdas run as expected the return received by the user or app is the eventbridge response. I can’t find any docs on how eventbridge handles responses for http requests through API gateway.
Does anyone have any ideas or docs to push me in the right direction.
Thanks!
In your setup it's not possible to have the Lambda response proxied back to the api request initiator, as your client is very much decoupled of the actual request processing.
Almost identical issue was experienced here
You need to rethink the process as a whole:
what operation you want to complete via the API request?
does the processing of the request really need to be asynchronous (= does it take long time to complete?)
can you handle the request with a Lambda function, delegate to sns from there and finally generate desired response back to the client?
So as it turns out the answer is yes and no for anyone coming across this in the future.
With the current setup another database is required and the responses can be inserted into it with a transaction ID. This transaction ID can be generated by the client during the request so a subsequent call to find the response in the table can be made.
Alternatively Websocket or GraphQL api’s or would allow for asynchronous invocation if really depends on your use case and accepted complexity.
Thanks for everyone’s inputs!
I am using AWS API Gateway with HTTP API which invokes a lambda function. However HTTP API doesn't include USAGE feature. According to my requirement I need to create a usage for a client depending on the status code of the response sent back by the lambda. Since I cant access the response sent by lambda in API Gateway, I am looking for an custom solution. I am planing to use STEP function.
For example:
Instead of API Gateway directly invoking a lambda function it can call a STEP function where I can execute LambdaA. next it would trigger LambdaB with response from LambdaA as input to LambdaB in a sequential manner. I don't know If this is the right approach
I would like to know what is best way of solving this problem...thanks in advance
I working on a project and I need to trigger a proxy API whenever a message is received by the AWS SQS Service. I went through couple of articles and found that API to SQS is possible but did not find anything related to SQS triggering API Gateway. Can somebody please guide.
It is not possible to invoke a Lambda function asynchronously with a proxy integration. You can do this with Lambda non-proxy integration.
Set up asynchronous invocation of the backend Lambda function - https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-integration-async.html
Another workaround is to use another function that is invoked synchronously by the API Gateway API and have that function invoke the function that is part of the Spring boo application asynchronously using the Lambda Invoke API or SDK equivalent.
https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html
For instance, you want Function A to be invoked asynchronously. To achieve this you would have the API Gateway API invoke Function B synchronously and have Function B invoke Function A asynchronously with the Invoke API.
Step Functions also cant be used as a workaround to invoke the REST APIs as this would not help. The Lambda functions are still invoked by the API Gateway API so you would still run into the limitation of a proxy integrations not being able to invoke Lambda asynchronously. You then decided that ECS would better suit your case as Lambda is not a good fit.
I currently have a Web hook that's calling AWS API Gateway -> AWS Lambda function proxy. I'd like to make the web hook more responsive and return an early reply while continuing processing in the Lambda.
I went ahead and did this early reply from the Lambda (Node v6.10) but it didn't appear to have improved responsiveness. Is API Gateway somehow waiting for the Lambda to finish executing despite having the response from the callback already?
The other idea is to post an SNS notification from Lambda and have a second Lambda listen and continue processing but would rather avoid that complication if there's a simpler way.
API Gateway currently only supports synchronous invocation (aka InvocationType: RequestResponse) of Lambda functions, so yes, it is waiting for the full response from the Lambda.
To support your use case, you could use SNS or an another intermediary AWS service like Kinesis, SQS, etc. But you could also do it with Lambda alone. Have the first Lambda function trigger a second Lambda function asynchronously with InvocationType: 'Event', this will achieve the effect you desire.
See this post for more details: https://stackoverflow.com/a/31745774/5705481