Developing AWS Serverless Messaging System
Tags: dotnet, sqs, aws, serverless
Published: 2020-02-18 06:03:21

This article was originally published at:  [https://www.ahmetkucukoglu.com/en/developing-aws-serverless-messaging-system/](https://www.ahmetkucukoglu.com/en/developing-aws-serverless-messaging-system/)


## 1. Introduction

This article will be about how to develop the messaging system with the serverless approach. We will use AWS as a cloud provider. We will prefer .NET Core as the language.

In this part, I will set up the scenario and give preliminary information about what will be the result.

Our RESTful API endpoints will be as follows.

[POST] api/comments  
[GET] api/comments

We will use the AWS services below.

**API Gateway :** It will provide the endpoints we need for the RESTful API.  
**Lambda :** It will provide us to write function for the GET and POST requests.  
**SQS :** It will provide a messaging system. In POST request, we will send the comment texts to the queue for later processing.  
**Comprehend :** It will provide machine learning system. We will use it to detect the languages of the comment texts entered.  
**DynamoDB :** It will provide NoSQL solution. In the POST request, we will write the data to the DynamoDB.  
**S3 :** It will provide our code to be versioned and stored after each deployment.  
**CloudFormation :** It will provide us to create and manage automatically all services mentioned above.

When the project is completed, the architecture on AWS will be as follows.

![Serverless Messaging Architecture](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/Serverless-Messaging-System-on-AWS-1024x607.png)

We will get the comment text from the API with the POST method. We will save this comment to DynamoDB and return result. Since it will take a long time to automatically detect the language of the comment text, we will send the comment text to the queue. The lambda function, which listens to the messages in the queue will use the Comprehend service to detect the language. After getting the result, the record in DynamoDB will be updated. We will return the final version of the comment texts with the GET method from the API.

## 2. Preparing Development Environment

In this part, we will arrange the development environment. We can apply the second part of the article, [Developing AWS Serverless RESTful API](https://www.ahmetkucukoglu.com/en/developing-aws-serverless-restful-api/). We need to include the following policies in the permission section.

-   AmazonSQSFullAccess
-   ComprehendFullAccess

## 3. Preparing API Project

In this part, we will create the project in its simplest form and make deployment. We will not send data to DynamoDB and SQS yet. We will send request to endpoints and get response.

Create the project folder with the command line below.

```
mkdir serverless-sqs
cd serverless-sqs
code .
```

We will create two separate projects. One is the API project and the other is the Consumer project, which listens to the messages in the queue. Create an api folder with the following command line from the terminal from VS Code and enter the folder.

```
mkdir api
cd api
```

Create the serverless project with the command line below.

```
serverless create --template aws-csharp --name comments-api
```

We will see a file named "Handler.cs". This is the entry point of the application. We will need two functions, GET and POST. While this is possible in Nodejs, it is troublesome in .NET Core. Because we will need to edit the output manually and it is something you would not like :). Therefore, we will make arrangements for the ASP.NET Core API to run when a request comes to lambda. In this way, we will direct the requests to actions on the controller with the help of proxy.

Start with cleaning first. Delete the file "Handler.cs". Delete the installed packages with the following command lines.

```
dotnet remove package Amazon.Lambda.Core
dotnet remove package Amazon.Lambda.Serialization.Json
```

Change the "hello.zip" in the build.cmd and build.sh files in the project as "api-handler.zip". When we build the project, an artifact named properly shall be created. :) Shortly after, I will show how to use this artifact in serverless.yml.

We need to install some packages because we will run ASP.NET Core API. Install the packages with the following command lines.

```
dotnet add package Microsoft.AspNetCore.App -v 2.1.4
dotnet add package Amazon.Lambda.AspNetCoreServer
dotnet add package AWSSDK.Extensions.NETCore.Setup
```

Create a file named "Startup.cs" and paste the following code.

{% gist https://gist.github.com/ahmetkucukoglu/ac473bf7217a688fb1d20af1593b0fdf %}

Now, set the entry point of the lambda. Create a file named "LambdaEntryPoint.cs" and paste the code below.

{% gist https://gist.github.com/ahmetkucukoglu/ab177b5387ef1b934eb3477f87f69011 %}

Update the serverless.yml file with the code below.

{% gist https://gist.github.com/ahmetkucukoglu/fae5a3b91393c657bafec86e543caf7a %}

On the 16th line, specify the entry point of the application as a LambdaEntryPoint file.  
On the 19th line, create a proxy endpoint in the API Gateway. In this way, we transfer the requests coming to API Gateway directly to the Controllers matching in the project.  
On the 23th line, specify the path of the artifact we need when deploying the application.

Now we can create Controller. Create a folder named "Controllers" and create a file named "CommentsController.cs" in it. Paste the code below.

{% gist https://gist.github.com/ahmetkucukoglu/2d6eb3d2780d603643c2359a1895e3ab %}

Create a folder named "Models" and create a file named "CommentsPostRequest.cs" in it. Paste the code below.

{% gist https://gist.github.com/ahmetkucukoglu/0304c6f9cc8a9aac5efcf3e06f4d0f8e %}

Build the code with the command line below.

```
build
```

![Serverless API build output](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/01-Build-1024x504.png)

Make our first deployment to AWS with the command line below.

```
serverless deploy
```

After the deployment process, it will write 1 endpoint and 1 API Key on the console.

![Serverless deployment output](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/Step-1-1024x406.png)

Let's look at what changed in AWS after the process.

A Stack has been created in the [Cloud Formation](https://eu-central-1.console.aws.amazon.com/cloudformation/home?region=eu-central-1).

![Serverless API CloudFormation](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/003-CloudFormation-1024x532.png)

Our code has been sent to [S3](https://s3.console.aws.amazon.com/s3/home?region=eu-central-1).

![Serverless API S3](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/004-S3-1024x531.png)

[API Gateway](https://eu-central-1.console.aws.amazon.com/apigateway/home?region=eu-central-1) has been created for the endpoints.

![Serverless API Gateway](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/005-API-Gateway-1024x532.png)

[Lambda](https://eu-central-1.console.aws.amazon.com/lambda/home?region=eu-central-1#/functions) function has been created.

![Serverless API Lambda](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/006-Lambda-1024x532.png)

## 4. Integrating DynamoDB and SQS into API Project

In this part, we will write the comment text to DynamoDB in the POST request coming from the API and send a message the queue in SQS. In the GET request, we will return the comment texts from DynamoDB.

Install the packages we need with the following command lines.

```
dotnet add package AWSSDK.DynamoDBv2
dotnet add package AWSSDK.SQS
```

Update the serverless.yml file as follows.

{% gist https://gist.github.com/ahmetkucukoglu/b77753335047d442ec7aa25979fbf368 %}

On the 43th line, define the resource that will be created for DynamoDB.  
On the 46th line, name the table.  
On the 66th line, export the ARN of DynamoDB that we have created. On the 72th line, export the name of the table. We will use DynamoDB by importing this ARN and the table name we have exported to the consumer project.  
On the 11th line, assign the name of the table we have created as environment variable.  
On the 23th line, give full access to DynamoDB, which we have created on lambda.

On the 40th line, define the resource that will create the SQS.  
On the 43th line, name the queue.  
On the 78th line, export the ARN of the SQS we have created. We will use SQS by importing this ARN we have exported to the consumer project.  
On the 13th line, assign the name of the table we have created as environment variable.  
On the 18th line, give full access to lambda that it to SQS.

Update the Startup.cs file as follows.

{% gist https://gist.github.com/ahmetkucukoglu/2eb477946fa09ad2b69beca74f816708 %}

On the 12th and 1t3th lines, register DynamoDB and SQS clients to IOC Container.

Create a file named "CommentsGetResponse.cs" under the Models folder and paste the code below.

{% gist https://gist.github.com/ahmetkucukoglu/63787ceb00a549c310c5fd6f95f5b52d %}

Create a file named "CommentsQueueRequest.cs" under the Models folder and paste the code below.

{% gist https://gist.github.com/ahmetkucukoglu/21c524b3638a145d19fd130c88f18844 %}

Update the CommentsController.cs file with the code below.

{% gist https://gist.github.com/ahmetkucukoglu/49a471d7e590485a9b014fe59260bd17 %}

On the 39th line, return the comment texts from DynamoDB.  
On the 61th line, save the comment text to DynamoDB.  
On the 76th line, send a message to the queue we have created in SQS to be processed.

Build the code with the command line below.

```
build
```

![Serverless consumer build output](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/07-Build-1024x513.png)

Make our deployment to AWS with the command line below.

```
serverless deploy
```

![Serverless consumer deployment output](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/08-Deploy-1024x424.png)

Make a POST request.

![Serverless POSTMAN POST](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/11-POST-1024x563.png)

Make a GET request.

![Serverless POSTMAN GET](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/12-GET-1024x564.png)

Let's look at what changed in AWS after the process.

A table has been created in [DynamoDB](https://eu-central-1.console.aws.amazon.com/dynamodb/home?region=eu-central-1#tables:selected=Comments;tab=items) and the record has been sent to the table with the POST request.

![Serverless API DynamoDB](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/009-DynamoDB-1024x532.png)

A queue has been created in [SQS](https://eu-central-1.console.aws.amazon.com/sqs/home?region=eu-central-1) and a message has been sent to the queue with the POST request.

![Serverless API SQS](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/010-SQS-1024x532.png)

## 5. Preparing the Consumer Project

In this part, we will create the consumer project, which will process the messages we have sent to the queue in SQS. Create the consumer folder by running the following command line in the terminal from VS Code and enter it.

```
mkdir consumer
cd consumer
```

Create our serverless project with the command line below.

```
serverless create --template aws-csharp --name comments-consumer
```

Start with cleaning first again. Delete the file named Handler.cs.

Change the "hello.zip" in the build.cmd and build.sh files in the project as "consumer-handler.zip". When we build the project, an artifact named properly shall be created. Shortly after, I will show how to use this artifact in serverless.yml.

It is necessary to install SQSEvents package to listen to messages in the queue in SQS, and Comprehend package to find the language of the comment text, and DynamoDB package for NoSQL. Install the packages with the following command lines.

```
dotnet add package Amazon.Lambda.SQSEvents
dotnet add package AWSSDK.Comprehend
dotnet add package AWSSDK.DynamoDBv2
```

Create a folder named "Models" and create a file named "CommentsQueueRequest.cs" in it and paste the code below.

{% gist https://gist.github.com/ahmetkucukoglu/99e58024e2f699cf6c1a25779df83463 %}

Create a file named "ConsumerHandler.cs" and paste the code below.

{% gist https://gist.github.com/ahmetkucukoglu/865896c3f22a948e67e93a655645d0cc %}

On the 21th line, take the message in SQS. Since we will take the messages one by one in our example, it is enough to take the value in the zero index. For example, if we were going to take the messages ten by ten, we would have to loop them.  
On the 32th line, make the language querying of the comment text from the Comprehend service.  
On the 48th line, update the line in DynamoDB.

Update the serverless.yml file with the code below.

{% gist https://gist.github.com/ahmetkucukoglu/4533c3a8aefc20c5e160e31fd110bd7d %}

On the 9th line, import the name of the DynamoDB table that we have exported in api project.  
On the 13th line, give full access to the SQS we have created.  
On the 18th line, give access to the language querying function in the Comprehend service.  
On the 23th and 24th lines, give access to DynamoDB.  
On the 35th line, connect the trigger to the queue in SQS.  
On the 38th line, define that the messages should be transmitted to lambda one by one.

Build our code with the command line below.

```
build
```

![Serverless consumer build output](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/13-Build-1024x518.png)

Make our deployment with the command line below.

```
serverless deploy
```

![Serverless consumer deployment output](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/14-Deploy-1024x497.png)

Let's look at what changed in AWS after the process.

A stack has ben created in [Cloud Formation](https://eu-central-1.console.aws.amazon.com/cloudformation/home?region=eu-central-1).

![Serverless Consumer CloudFormation](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/015-CloudFormation-1024x532.png)

Our code has been sent to [S3](https://s3.console.aws.amazon.com/s3/home?region=eu-central-1).

![Serverless Consumer S3](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/016-S3-1024x532.png)

Our [Lambda](https://eu-central-1.console.aws.amazon.com/lambda/home?region=eu-central-1#/functions) function has been created.

![Serverless Consumer Lambda](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/017-Lambda-1024x532.png)

In the previous part, we have made a POST request and send a message on the queue in SQS. Now, that message has been processed. When you make a GET request, you will see that the language of the comment text is updated.

![Serverless POSTMAN GET](https://www.ahmetkucukoglu.com/wp-content/uploads/2019/11/18-GET-1024x565.png)

You can continue trying by making POST requests.

You can access the final version of the project from [Github](https://github.com/ahmetkucukoglu/serverless-queuing).

Good luck.