Is it the strongest or easy?
Common as a serverless configuration API Gateway & Lambda
** API Gateway has a 29 second limit **, ** Lambda has a 15 minute limit **
While making full use of Lambda's performance To fill that gap ** I want to make an asynchronous API with as simple a configuration as possible ** I think there is.
What you need at that time
--API for kicking Lambda --API to determine if the kicked Lambda is complete and receive a response
I think it is, but the Step Functions below have both **
Step Functions
In Step Functions Make workflows visually and handsome, such as linking microservices Can be configured.
** Official example: **
https://aws.amazon.com/jp/blogs/news/new-aws-step-functions-build-distributed-applications-using-visual-workflows/
It's dangerous I think I can do anything
By defining Lambda as a Task You can incorporate it into this workflow.
By the way, this is the one I will make this time (cute)
I will make it like this
APIfor start-execution to kick the above
Lambda API
for describe-execution to receive response from Lambda
(The name can be anything)
** Both are POST **
Serverless Framework
https://github.com/ChaseSan/async-api-sample
I will actually make it with SLS
It's much easier than making it with CFn,
You need to include serverless-step-functions
as a plugin
serverless.yml
plugins:
- serverless-step-functions
The function is created like this ** Ramen timer **
serverless.yml
functions:
async-api:
handler: app.lambda_handler
name: async-api-${self:provider.stage}
environment:
TIMER: 30
app.py
import os
from time import sleep
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
def lambda_handler(event, context):
logger.info(f"event: {event}")
seconds = int(os.environ.get("TIMER"))
sleep(seconds)
return {"message": "The ramen is boiled. If you don't eat it quickly, it will grow."}
The definition of Step Functions looks like this
When using the serverless-step-functions
plugin
Also write the API Gateway definition inside the stateMachines
block
serverless.yml
stepFunctions:
stateMachines:
state-machine:
name: state-machine-${self:provider.stage}
events:
- http:
path: ${self:custom.basePath}/start-execution
method: post
action: StartExecution
iamRole:
Fn::GetAtt: [AsyncApiRole, Arn]
request:
template:
application/json: |-
{
"stateMachineArn":"arn:aws:states:#{AWS::Region}:#{AWS::AccountId}:stateMachine:state-machine-${self:provider.stage}"
}
- http:
path: ${self:custom.basePath}/describe-execution
method: post
action: DescribeExecution
iamRole:
Fn::GetAtt: [AsyncApiRole, Arn]
response:
template:
application/json: |-
{
"input": $util.parseJson($input.json('$.input')),
#if($input.path('$.output') != "")
"output": $util.parseJson($input.json('$.output')),
#end
"status": $input.json('$.status')
}
definition:
StartAt: async-api-task
States:
async-api-task:
Type: Task
Resource:
Fn::GetAtt: [async-api, Arn]
End: true
** Points **
--In start-execution
, describe StartExecution in ʻevents.http.action. --ʻEvents.http.request.template
describes Arn of StateMachine to be executed in Json format.
--In describe-execution
, describe DescribeExecution in ʻevents.http.action. --Description the response in Json format in ʻevents.http.request.template
{
"response": $input.json('$'),
}
Anyway, all the contents of DescribeExecution will be returned. It would be better to return only what you need in terms of interface (probably)
Let's deploy and move
sls deploy
Try it with the endpoint that appears in the console
start-execution Use the obtained ʻexecutionArn` to hit the following API
describe-execution
Something has returned.
status
is RUNNING
.
It seems that ramen hasn't been made yet.
Let's hit it again after a while
Oh, status
became SUCCEEDED
, and you told me that the ramen was completed.
No, it ’s really easy. Without this, I would have to make full use of Dynamo and SQS and implement it myself (hell).
Recommended Posts