The ubiquity of cloud computing has reduced the barrier to entry for many web scale use cases. Consider an IoT(Internet of things) setup where "things" send data to a back-end system. For argument's sake let's assume that no compute happens on the edge and events are submitted as they happen. From a scalability perspective, a number of considerations need to be made to ensure performance of the back-end systems. Some of these considerations involve the use of a queue as a buffer. Various message brokers exist out there which provide queuing services and cloud providers have implemented them as software-as-a-service products. How can one combine these  with other cloud services to build a scalable IoT events sink?

The top three cloud providers; AWS, Azure and GCP (in my humble opinion) come with a bunch of technologies to support server-less compute. In the next sections we will implement a .NET Core  service that ingests events published to an SQS queue using AWS's lambda functions. This is the in for it.

Prerequisites

  • Visual studio 2019 installed.
  • Basic understanding of C#.
  • Access to an AWS console with permissions to an SQS queue.

Assumptions

  • There exists an SQS instance.
  • There exists a lambda function.
  • The lambda function has a trigger mapped to the SQS instance above.

Procedure

In Visual Studio create a new class library project

new class library project

Rename the default class: Class1 to LambdaFunctionEntry which is the naming convention for lambda entry classes. Before we start editing the code we need to install all the required packages.

Package installation

  • install-package Amazon.Lambda.Core
  • install-package Amazon.Lambda.SQSEvents
  • install-package Amazon.Lambda.Serialization.SystemTextJson

Decorate the namespace with the assembly attribute as below. This instructs the lambda function to use the Amazon.Lambda.Serialization.SystemTextJson namespace for the serialization and deserialization of the function's inputs. The library is based on System.Text.Json language APIs.

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

The entry class is ready for an entry function so let us add one.

public async Task FunctionHandler(SQSEvent invocationEvent, ILambdaContext context)
    {
        await Task.FromResult(0); // dummy awaiter

        LambdaLogger.Log(JsonSerializer.Serialize(invocationEvent));
    }

Take note of the method signature. The parameter invocationEvent of type SQSEvent contains the data received from an instance of SQS.  SQSEvent has a property; Records which is a list of Messages as read from the queue.

The full code is given below.

using Amazon.Lambda.Core;
using Amazon.Lambda.SQSEvents;
using System.Threading.Tasks;
using System.Text.Json;

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace decoded_lambda_demo
{
    public class LambdaFunctionEntry
    {
        public async Task FunctionHandler(SQSEvent invocationEvent, ILambdaContext context)
        {
            await Task.FromResult(0); // dummy awaiter

            LambdaLogger.Log(JsonSerializer.Serialize(invocationEvent));
        }
    }
}

The above script is well and good but running it in the development machine doesn't solve anyone's problem, does it? So how do we deploy it? We make use of Amazon.Lambda.Tools .NET Core Global Tool to create a compressed zip package that will be uploaded to the AWS console.  Install the toolkit with the command below.

dotnet tool install -g Amazon.Lambda.Tools

Then package the lambda package as below.

dotnet lambda package

Assuming that the lambda function has already been created. Upload the package on the lambda function code section.

We need to make a few configuration changes to ensure that the uploaded code can be invoked giving the expected results. All Configurations below can be left to their default values with the exception of the Handler. See the format below on how to construct the Handler value.

Handler format : Assembly::Namespace.ClassName::MethodName

For our example this will be:

decoded-lambda-demo::decoded_lambda_demo.LambdaFunctionEntry::FunctionHandler

Publishing a message to the given SQS instance will trigger the function and the content of the message will be logged to CloudWatch.

Conclusion

This is an easy way to get started with Serverless compute for tasks that do not need heavy lifting from a dependency perspective in AWS. This post does not take into consideration dependency management which is probably worthy of a post on its own.  The demo makes a number of assumptions on the part of developers making use of it including how to configure lambda instances. Have you used AWS lambda before or even Azure functions? What was your experience? Please share your feedback even on the clarity of this walk-through and I will be glad to extend it.

PS: The code used here can be found in this GitHub repository.

You've successfully subscribed to Decoded For Devs
Welcome back! You've successfully signed in.
Great! You've successfully signed up.
Your link has expired
Success! Your account is fully activated, you now have access to all content.