AWS Lambda

 AWS Lambda (or Lambda for short) is a serverless computing service provided by AWS. In this chapter we are going to be using Lambda to build our serverless application. And while we don’t need to deal with the internals of how Lambda works, it’s important to have a general idea of how your functions will be executed.

Lambda Specs

Let’s start by quickly looking at the technical specifications of AWS Lambda. Lambda supports the following runtimes.

  • Node.js 16.x, 14.x and 12.x
  • Java 11 and 8
  • Python 3.9, 3.8, 3.7 and 3.6
  • .NET 6, 3.1, 3.0 and 2.2
  • Go 1.x
  • Ruby 2.7
  • Rust

Note that, .NET Core 2.2 and 3.0 are supported through custom runtimes.

See AWS for latest information on available runtimes.

Each function runs inside a container with a 64-bit Amazon Linux AMI. And the execution environment has:

  • Memory: 128MB - 10240MB, in 1 MB increments
  • Ephemeral disk space: 512MB - 10240MB, in 1 MB increments
  • Max execution duration: 900 seconds
  • Compressed package size: 50MB
  • Uncompressed package size: 250MB
  • Container image package size: 10GB

You might notice that CPU is not mentioned as a part of the container specification. This is because you cannot control the CPU directly. As you increase the memory, the CPU is increased as well.

The ephemeral disk space is available in the form of the /tmp directory. You can only use this space for temporary storage since subsequent invocations will not have access to this. We’ll talk a bit more on the stateless nature of the Lambda functions below.

The execution duration means that your Lambda function can run for a maximum of 900 seconds or 15 minutes. This means that Lambda isn’t meant for long running processes.

The package size refers to all your code necessary to run your function. This includes any dependencies (node_modules/ directory in case of Node.js) that your function might import. There is a limit of 250MB on the uncompressed package and a 50MB limit once it has been compressed. If you need more space, you can package your container as a Docker image which can be up to 10GB. We’ll take a look at the packaging process below.

Lambda Function

Finally here is what a Lambda function (a Node.js version) looks like.

Anatomy of a Lambda Function image

Here myHandler is the name of our Lambda function. The event object contains all the information about the event that triggered this Lambda. In the case of an HTTP request it’ll be information about the specific HTTP request. The context object contains info about the runtime our Lambda function is executing in. After we do all the work inside our Lambda function, we simply call the callback function with the results (or the error) and AWS will respond to the HTTP request with it.

Packaging Functions

Lambda functions need to be packaged and sent to AWS. This is usually a process of compressing the function and all its dependencies and uploading it to an S3 bucket. And letting AWS know that you want to use this package when a specific event takes place. To help us with this process we use the SST. We’ll go over this in detail later on in this guide.

Execution Model

The container (and the resources used by it) that runs our function is managed completely by AWS. It is brought up when an event takes place and is turned off if it is not being used. If additional requests are made while the original event is being served, a new container is brought up to serve a request. This means that if we are undergoing a usage spike, the cloud provider simply creates multiple instances of the container with our function to serve those requests.

This has some interesting implications. Firstly, our functions are effectively stateless. Secondly, each request (or event) is served by a single instance of a Lambda function. This means that you are not going to be handling concurrent requests in your code. AWS brings up a container whenever there is a new request. It does make some optimizations here. It will hang on to the container for a few minutes (5 - 15mins depending on the load) so it can respond to subsequent requests without a cold start.

Stateless Functions

The above execution model makes Lambda functions effectively stateless. This means that every time your Lambda function is triggered by an event it is invoked in a completely new environment. You don’t have access to the execution context of the previous event.

However, as noted in the optimization above, AWS will hang on to an existing container for a few minutes and use that to respond to any requests. So for that container instance, the code around the Lambda function will only be invoked once. While the actual Lambda function will be invoked for each request.

For example, the createNewDbConnection method below is called once per container instance and not every time the Lambda function is invoked. The myHandler function on the other hand is called on every invocation.

var dbConnection = createNewDbConnection();

exports.myHandler = function (event, context, callback) {
  var result = dbConnection.makeQuery();
  callback(null, result);
};

This caching effect of containers also applies to the /tmp directory that we talked about above. It is available as long as the container is being cached.

Now you can guess that this isn’t a very reliable way to make our Lambda functions stateful. This is because we just don’t control the underlying process by which Lambda is invoked or its containers are cached.

Pricing

Finally, Lambda functions are billed only for the time it takes to execute your function. And it is calculated from the time it begins executing till when it returns or terminates. It is rounded up to the nearest 1ms.

Note that while AWS might keep the container with your Lambda function around after it has completed; you are not going to be charged for this.

Lambda comes with a very generous free tier and it is unlikely that you will go over this while working on this guide.

The Lambda free tier includes 1M free requests per month and 400,000 GB-seconds of compute time per month. Past this, it costs $0.20 per 1 million requests and $0.00001667 for every GB-seconds. The GB-seconds is based on the memory consumption of the Lambda function. You can save up to 17% by purchasing AWS Compute Savings Plans in exchange for a 1 or 3 year commitment. For further details check out the Lambda pricing page.

In our experience, Lambda is usually the least expensive part of our infrastructure costs.

Next, let’s take a deeper look into the advantages of serverless, including the total cost of running our demo app.

Enter the Lambda Console

When you click here, the AWS Management Console will open in a new browser window, so you can keep this step-by-step guide open. In the top navigation bar, search for Lambda and open the AWS Lambda Console.


Select the Lambda blueprint

Blueprints provide example code to do some minimal processing. Most blueprints process events from specific event sources, such as Amazon S3, Amazon DynamoDB, or a custom application.

a.  In the AWS Lambda console, choose Create function.

Note: The console shows this page only if you do not have any Lambda functions created. If you have created functions already, you will see the Lambda > Functions page. On the list page, choose Create a function to go to the Create function page.


b.  Select use a blueprint.

c.  In the Filter box, enter hello-world-python and select the hello-world-python blueprint.

d.  Then choose Configure.

Configure and create your Lambda function

c. Runtime: Currently, you can author your Lambda function code in Java, Node.js, C#, Go, or Python. For this tutorial, use Python 3.7 as the runtime.

d. Handler: You can specify a handler (a method/function in your code) where AWS Lambda can begin executing your code. AWS Lambda provides event data as input to this handler, which processes the event.

In this example, Lambda identifies this from the code sample and this should be pre-populated with lambda_function.lambda_handler.

 
Invoke Lambda function and verify result

The console shows the hello-world-python Lambda function. You can now test the function, verify results, and review the logs.

a.  Select Configure Test Event from the drop-down menu called Test.


b.  The editor pops up so you can enter an event to test your function.  

  • Select Create new event.
  • Type in an event name like HelloWorldEvent.
  • Retain default setting of Private for Event sharing settings.
  • Choose hello-world from the template list.
  • You can change the values in the sample JSON, but don’t change the event structure. For this tutorial, replace value1 with hello, world!.

Select Create.

c. Choose Test.


d. Upon successful execution, view the results in the console:

  • The Execution results tab verifies that the execution succeeded.
  • The Function Logs section will show the logs generated by the Lambda function execution as well as key information reported in the Log output.


Monitor your metrics

AWS Lambda automatically monitors Lambda functions and reports metrics through Amazon CloudWatch. To help you monitor your code as it executes, Lambda automatically tracks the number of requests, the latency per request, and the number of requests resulting in an error and publishes the associated metrics. 

a. Invoke the Lambda function a few more times by repeatedly choosing the Test button. This will generate the metrics that can be viewed in the next step.


b. Select the Monitor tab to view the results.

c. Scroll down to view the metrics for your Lambda function.  Lambda metrics are reported through Amazon CloudWatch. You can leverage these metrics to set custom alarms. For more information about CloudWatch, see the Amazon CloudWatch Developer Guide.

The Monitoring tab will show seven CloudWatch metrics: Invocations, Duration, Error count and success rate (%), Throttles, Async delivery failures, IteratorAge, and Concurrent executions.

With AWS Lambda, you pay for what you use. After you hit your AWS Lambda free tier limit, you are charged based on the number of requests for your functions (invocation count) and the time your code executes (invocation duration).  For more information, see AWS Lambda Pricing.




Delete the Lambda function

While you will not get charged for keeping your Lambda function, you can easily delete it from the AWS Lambda console.  

a.  Select the Actions button and select Delete function.

b.  You will be asked to confirm your termination - select Delete.


 




No comments: