Links
Description
Serverless service / Function as a service allowing to run code without having to worry about underlying hardware and OS.
Event driven: the lambda is triggered by an event.
Pay only for what you use: per request and based on the duration of the code execution.
Use cases
- Data transformation (Kinesis Data Stream as input)
- File processing (when uploaded to S3 bucket)
- Website backend microservice
- Scheduled tasks
Bad use cases
- Long running processes (timeout after 15mn)
- Constant workload (no scalability and high cost)
- Large code base (needed to be loaded at startup)
- State management (lambda are stateless)
Anti-patterns
- Monolithic function
- increase package size
- hard to enforce least privilege permissions
- hard to upgrade, maintain and test
- Recursion
- Orchestration
- avoid complex workflow logic
- ties lambda with other systems
- instead consider AWS Step Functions or EventBridge
- Chaining (synchronously invoke another lambda)
- instead use EventBridge or QueueService
- Waiting (synchronously call services or databases)
- instead use asynchronous calls
Runtime
- OS
- Libraries
- Programming language (.NET, Node.js, Python, Go, Ruby, Java)
Environnement variables
DOTNET_STARTUP_HOOKS |
ex: path to an assembly to inject logging
|
Wrapper scripts
Execute the wrapper on top of the runtime and the lambda function.
- run shell commands and binaries
Use AWS_LAMBDA_EXEC_WRAPPER to point to your wrapper script.
Custom runtime
Provide your custom runtime.
- unsupported programming language
Method responsible for processing input events.
synchronous execution |
result returned to the calling app
|
asynchronous execution |
result sent to the configured destination otherwise lost
|
Using the C# 9's top-level statements feature, you generate an executable assembly which will be run by the Lambda. You provide Lambda only with the name of the executable assembly to run.
|
var handler = async (string argument1, ILambdaContext context) => { };
// bootstrap the Lambda runtime and pass it the handler method
await LambdaBootstrapBuilder.Create(handler, new DefaultLambdaJsonSerializer()).Build().RunAsync();
|
|
# install the VS project template
dotnet new install Amazon.Lambda.Templates
# install the command line tools
dotnet tool install -g Amazon.Lambda.Tools
|
C# class library
Function.cs
|
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace MyProject;
public class Function
{
public string FunctionHandler(string input, ILambdaContext context)
{
return input.ToUpper();
}
}
|
aws-lambda-tools-defaults.json
|
{
"Information": [ ],
"profile": "MyAwsProfile",
"region": "eu-central-1",
"configuration": "Release",
"function-architecture": "x86_64",
"function-runtime": "dotnet8",
"function-memory-size": 512,
"function-timeout": 30,
"function-handler": "MyProject::MyProject.Function::FunctionHandler"
}
|
Properties/launchSettings.json
|
{
"profiles": {
"Mock Lambda Test Tool": {
"commandName": "Executable",
"commandLineArgs": "--port 5050",
"workingDirectory": ".\\bin\\$(Configuration)\\net8.0",
"executablePath": "%USERPROFILE%\\.dotnet\\tools\\dotnet-lambda-test-tool-8.0.exe"
}
}
}
|
C# class library
On VS, if the extension AWS Toolkit is installed you have the AWS .NET Mock Lambda Test Tool available.
A debug configuration is created for you lambda.
Properties\launchSettings.json
|
{
"profiles": {
"Mock Lambda Test Tool": {
"commandName": "Executable",
"commandLineArgs": "--port 5050",
"executablePath": "%USERPROFILE%\\.dotnet\\tools\\dotnet-lambda-test-tool-8.0.exe",
"workingDirectory": ".\\bin\\$(Configuration)\\net8.0"
}
}
}
|
You have to create the debug configuration file for you lambda.
Properties\launchSettings.json
|
{
"profiles": {
"Mock Lambda Test Tool": {
"commandName": "Executable",
"commandLineArgs": "--port 5050",
"executablePath": "%USERPROFILE%\\.dotnet\\tools\\dotnet-lambda-test-tool-8.0.exe",
"workingDirectory": ".\\bin\\$(Configuration)\\net8.0",
"environmentVariables": {
"AWS_LAMBDA_RUNTIME_API": "localhost:5050",
"AWS_PROFILE": "MyProfile",
"AWS_REGION": "us-east-1"
}
}
}
}
|
|
dotnet lambda deploy-function [AssemblyName] --profile [Profile]
|
Call a lambda from code
|
var jsonSerializerOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters = { new JsonStringEnumConverter() }
};
var amazonLambdaClient = new AmazonLambdaClient();
var request = new InvokeRequest
{
FunctionName = functionName,
Payload = JsonSerializer.Serialize(myObject, jsonSerializerOptions),
LogType = LogType.Tail
};
var response = await this.amazonLambdaClient.InvokeAsync(request);
if(response.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
var payload = Encoding.ASCII.GetString(response.Payload.ToArray()); // to debug only
var result = JsonSerializer.Deserialize<AwsJobResult<LambdaJob>>(response.Payload, jsonSerializerOptions);
}
|
Errors
The Lambda on AWS has wrongly set the handler to LambdaTest.
AWS - Lambda - Functions - select your function - Code tab - Runtime settings - Edit - change the Handler