Introduction#
GitHub shows a decouple architecture by using aws sqs. There are cases: a) lambda takes more than 29 seconds to process a heavy task b) high number of requests comming at the api gateway, and sqs can help to decouple the requests and the processing.
Architecrture#
API gateway integerates with SQS queue via aws_apigateway.AwsIntegration class and API Gateway need a role or granted to write messages to the queue. Note After the message successuflly processed by the lambda, need to return statusCode: 200 to the SQS queue, so the queue will delete the processed message. Fail/exception messages will be put in a dead letter queue (DLQ)
Role to enable API Gateway writting messages to the SQS queue#
const role = new aws_iam.Role(this, 'apiGatewayWriteToSqsRole', {assumedBy: new aws_iam.ServicePrincipal('apigateway.amazonaws.com')})role.attachInlinePolicy(new aws_iam.Policy(this, 'writeToSqsPolicy', {statements: [new aws_iam.PolicyStatement({effect: aws_iam.Effect.ALLOW,actions: ['sqs:SendMessage'],resources: [queue.queueArn]})]}))
API Gateway#
const api_gw = new aws_apigateway.RestApi(this, 'apiGatewaySqsDemo', {restApiName: 'api-gateway-sqs-demo'})
API Gateway integration with SQS queue
const integration = new aws_apigateway.AwsIntegration({service: 'sqs',path: 'sqsQueueApiGatewayDemo',integrationHttpMethod: 'POST',options: {credentialsRole: role,requestParameters: {'integration.request.header.Content-Type': `'application/x-www-form-urlencoded'`},requestTemplates: {'application/json': `Action=SendMessage&MessageBody=$util.urlEncode("$method.request.querystring.message")`},integrationResponses: [{statusCode: '200',responseTemplates: {'application/json': `{'done': true}`}}]}})
API Gateway resource or path
const resource = api_gw.root.addResource('queue')
API Gateway add method
resource.addMethod('GET', integration, {methodResponses: [{ statusCode: '200' }]})
Lambda function to process messages from the queue#
create a Lambda function
const fn = new aws_lambda.Function(this, 'lambdaConsumeSqsMessageDemo', {runtime: aws_lambda.Runtime.PYTHON_3_8,code: aws_lambda.Code.fromAsset(path.join(__dirname, 'lambda')),handler: 'index.handler'})
lambda resource event to trigger lambda by the queue
fn.addEventSource(new SqsEventSource(queue, {batchSize: 1,maxBatchingWindow: Duration.minutes(1),reportBatchItemFailures: true}))
grant lambda to publish messages to a SNS topic
// existing topicconst topic = aws_sns.Topic.fromTopicArn(this,'lambdaSendMessageToSnsDemo','arn:aws:sns:ap-southeast-1:account_id:CodePipelineNotification')// grant publish to lambdatopic.grantPublish(fn)