├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── src └── app.py └── template.yaml /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Testing maximum concurrency of AWS Lambda functions when using Amazon SQS as an event source 2 | 3 | This AWS sample demonstrates how the maximum concurrency configuration for SQS as an event source helps control the Lambda function concurrency. This SAM template defines two Lambda functions and two SQS queues - one with maximum concurrency set to 5, another with [reserved concurrency](https://docs.aws.amazon.com/lambda/latest/operatorguide/reserved-concurrency.html) set to 5. By sending the same traffic to the SQS queue, users can observe the difference in how Lambda processes the SQS messages through the provided CloudWatch dashboards. You can read more about this feature in [AWS documentation](tbd) and or in this [blog](tbd) 4 | 5 | ## Step to run the demo 6 | Running this demo requires the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and the [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html). After installing both CLIs, clone this GitHub repository and navigate to the root of the directory. 7 | ``` 8 | git clone https://github.com/aws-samples/aws-lambda-amazon-sqs-max-concurrency 9 | 10 | cd aws-lambda-amazon-sqs-max-concurrency 11 | ``` 12 | ### Deploying the SAM template 13 | First build your SAM template with the [build](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-build.html) command to prepare for deployment in your AWS environment. 14 | ``` 15 | sam build 16 | ``` 17 | Then use the [deploy](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html) command to deploy the resources in your account. 18 | ``` 19 | sam deploy --guided 20 | ``` 21 | After walking through the deploy command, you can track the progress through the CLI or by navigating to the [AWS CloudFormation](http://console.aws.amazon.com/cloudformation) page in your AWS console. It will take a few minutes to complete the provisioning of resources. 22 | 23 | ### Running the demo 24 | The deployed Lambda function code simply sleeps for 10 seconds before returning a 200 response. This allows for reaching a high Lambda function concurrency number with only a small number of messages. You can add 25 messages to a queue using the following command. 25 | ``` 26 | for i in {1..25}; do aws sqs send-message --queue-url --message-body testing; done 27 | ``` 28 | You will need to include your queue URL in the above command. The URLs are available in the Outputs tab in the console, or you can navigate to the SQS console to find the queue URLs. 29 | 30 | After sending messages to both queues, click on the dashboard URL available in the Outputs tab to navigate to the CloudWatch dashboard. 31 | 32 | ### Validating results 33 | Both Lambda functions should have the same number of invocations, and the same concurrent invocations fixed at 5. However, you can see that the ReservedConcurrencyFunction experienced throttling, and messages were sent to the corresponding DLQ, whereas MaxConcurrencyFunction did not. 34 | 35 | ### Clean up 36 | To remove all the resources created while following this demo, use the [delete](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-delete.html) command and follow the prompts. 37 | ``` 38 | sam delete 39 | ``` 40 | 41 | ## Security 42 | 43 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 44 | 45 | ## License 46 | 47 | This library is licensed under the MIT-0 License. See the LICENSE file. 48 | 49 | -------------------------------------------------------------------------------- /src/app.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | 4 | def lambda_handler(event, context): 5 | time.sleep(10) 6 | return { 7 | 'statusCode': 200, 8 | 'body': json.dumps('Hello from Lambda!') 9 | } -------------------------------------------------------------------------------- /template.yaml: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | AWSTemplateFormatVersion: '2010-09-09' 5 | Transform: AWS::Serverless-2016-10-31 6 | Description: Template to demonstrate maximum concurrency for Lambda function when using SQS queue as as event source. 7 | 8 | Globals: 9 | Function: 10 | Timeout: 15 11 | CodeUri: src/ 12 | Runtime: python3.9 13 | 14 | Resources: 15 | ReservedConcurrencyDeadLetterQueue: 16 | Type: AWS::SQS::Queue 17 | 18 | ReservedConcurrencyQueue: 19 | Type: AWS::SQS::Queue 20 | Properties: 21 | DelaySeconds: 0 22 | RedrivePolicy: 23 | deadLetterTargetArn : !GetAtt ReservedConcurrencyDeadLetterQueue.Arn 24 | maxReceiveCount : 1 25 | VisibilityTimeout: 20 26 | 27 | MaxConcurrencyDeadLetterQueue: 28 | Type: AWS::SQS::Queue 29 | 30 | MaxConcurrencyQueue: 31 | Type: AWS::SQS::Queue 32 | Properties: 33 | DelaySeconds: 0 34 | RedrivePolicy: 35 | deadLetterTargetArn : !GetAtt MaxConcurrencyDeadLetterQueue.Arn 36 | maxReceiveCount : 1 37 | VisibilityTimeout: 20 38 | 39 | MaxConcurrencyFunction: 40 | Type: AWS::Serverless::Function 41 | Properties: 42 | Handler: app.lambda_handler 43 | Events: 44 | SQSEventFromMax: 45 | Type: SQS 46 | Properties: 47 | Queue: !GetAtt MaxConcurrencyQueue.Arn 48 | BatchSize: 1 49 | Enabled: true 50 | ScalingConfig: 51 | MaximumConcurrency: 5 52 | 53 | ReservedConcurrencyFunction: 54 | Type: AWS::Serverless::Function 55 | Properties: 56 | ReservedConcurrentExecutions: 5 57 | Handler: app.lambda_handler 58 | Events: 59 | SQSEventFromReserved: 60 | Type: SQS 61 | Properties: 62 | Queue: !GetAtt ReservedConcurrencyQueue.Arn 63 | BatchSize: 1 64 | Enabled: true 65 | 66 | CloudWatchDashboard: 67 | Type: AWS::CloudWatch::Dashboard 68 | Properties: 69 | DashboardName: Lambda-SQS-concurrency-monitoring 70 | DashboardBody: 71 | !Sub 72 | - | 73 | { 74 | "widgets": [ 75 | { 76 | "height": 4, 77 | "width": 16, 78 | "y": 0, 79 | "x": 0, 80 | "type": "metric", 81 | "properties": { 82 | "metrics": [ 83 | [ "AWS/SQS", "ApproximateNumberOfMessagesVisible", "QueueName", "${MaxConcurrencyDeadLetterQueue}" ], 84 | [ "...", "${ReservedConcurrencyDeadLetterQueue}" ] 85 | ], 86 | "sparkline": false, 87 | "view": "singleValue", 88 | "region": "${Region}", 89 | "period": 900, 90 | "stat": "Maximum", 91 | "title": "Approximate number of messages visible in the DLQ" 92 | } 93 | }, 94 | { 95 | "height": 7, 96 | "width": 8, 97 | "y": 8, 98 | "x": 0, 99 | "type": "metric", 100 | "properties": { 101 | "metrics": [ 102 | [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "${MaxConcurrencyFunction}" ], 103 | [ ".", "Throttles", ".", ".", { "color": "#d62728", "stat": "Sum" } ] 104 | ], 105 | "view": "timeSeries", 106 | "stacked": false, 107 | "region": "${Region}", 108 | "period": 60, 109 | "stat": "Maximum", 110 | "title": "Max Concurrency Lambda Function" 111 | } 112 | }, 113 | { 114 | "height": 7, 115 | "width": 8, 116 | "y": 8, 117 | "x": 8, 118 | "type": "metric", 119 | "properties": { 120 | "metrics": [ 121 | [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "${ReservedConcurrencyFunction}", { "stat": "Maximum" } ], 122 | [ ".", "Throttles", ".", ".", { "color": "#d62728" } ] 123 | ], 124 | "view": "timeSeries", 125 | "stacked": false, 126 | "region": "${Region}", 127 | "title": "Reserved Concurrency Lambda Function", 128 | "period": 60, 129 | "stat": "Sum" 130 | } 131 | }, 132 | { 133 | "type": "metric", 134 | "x": 0, 135 | "y": 4, 136 | "width": 16, 137 | "height": 4, 138 | "properties": { 139 | "metrics": [ 140 | [ "AWS/Lambda", "Invocations", "FunctionName", "${MaxConcurrencyFunction}", { "color": "#ff7f0e" } ], 141 | [ "...", "${ReservedConcurrencyFunction}", { "color": "#2ca02c" } ] 142 | ], 143 | "sparkline": false, 144 | "view": "singleValue", 145 | "region": "${Region}", 146 | "period": 900, 147 | "stat": "Sum", 148 | "title": "Total invocations in the last 15 minutes" 149 | } 150 | } 151 | ] 152 | } 153 | - 154 | MaxConcurrencyDeadLetterQueue: !GetAtt MaxConcurrencyDeadLetterQueue.QueueName 155 | ReservedConcurrencyDeadLetterQueue: !GetAtt ReservedConcurrencyDeadLetterQueue.QueueName 156 | Region: !Ref AWS::Region 157 | MaxConcurrencyFunction: !Ref MaxConcurrencyFunction 158 | ReservedConcurrencyFunction: !Ref ReservedConcurrencyFunction 159 | 160 | Outputs: 161 | MaxConcurrencyQueueURL: 162 | Description: URL of the SQS queue which sends messages to the Lambda function with the max concurrency configured as 5 163 | Value: !Ref MaxConcurrencyQueue 164 | 165 | ReservedConcurrencyQueueURL: 166 | Description: URL of the SQS Queue which sends messages to the Lambda function with max concurrency configured as 5 167 | Value: !Ref ReservedConcurrencyQueue 168 | DashboardURL: 169 | Description: Custom CloudWatch dashboard that highlight SQS and Lambda metrics relevant to maximum and reserved concurrency 170 | Value: !Sub 171 | - https://${Region}.console.aws.amazon.com/cloudwatch/home#dashboards:name=Lambda-SQS-concurrency-monitoring 172 | - Region: !Ref AWS::Region 173 | --------------------------------------------------------------------------------