In the current software development industry, where “Agile” ways of working and “microservices” has been the top searched keywords as well as skills in the market. There are many ways of implementing a solution which can be suite agile ways as well develop microservice based applications. We will be demonstrating a serverless and to some extent stateless way to implement microservices in Amazon Web Services.
Before the whole microservices came into the picture, All the development was done mostly on a larger code package with lots of overhead in syncing the code, releasing proper functions etc.
Currently, Umpteen frameworks are readily available for most of the computing languages and many cloud providers are evolving with deploying these frameworks in the easily automated ways.
Below picture shows the tools, services and frameworks offered by Microsoft, Amazon and Google
In our example, we will showcase the capabilities of Serverless and Stateless architecture using the following:
- Language : Python
- DB : SQL
- AWS : Lambda , API Gateway
- Framework : SAM
We have a fleet of microservices which will be doing CRUD operations in Amazon Aurora DB (MYSQL based). To make the design more scalable and less spaghetti, we have designed the schema to enable the development of the functions in a more data driven model.
This table contains the structure of the other tables which will store the relevant functional data.
For e.g.: If there is a table which stores task related data, we will be adding the following values in the master_table
1, id, task_data
2, name, task_data
3, desc, task_data
4, status , task_data
The above entries will be interpreted in the microservice code as a tabular structure:
Advantage of this implementation: Future modifications in the definitions of the table will be less headache to implement on the functional code.
However, the implementation of the above is not part of the scope of this document.
SQL Transaction Logging: In addition to the AWS provided logging mechanism, we have added another layer of tracing the SQL transactions for the architecture. For each of the SQL which will be formed dynamically based on the API invocation will be stored in the DynamoDB for future traceability matrix creation.
We have decoupled the implementations in the following layers to enable agile developments and faster deployment times:
- Front facing restful API’s
- Business Layer Lambda’s
- DB Layer Lambda’s
There are multiple ways to connect the serverless lambda’s hosted for different purposes.
One can connect the lambdas with an external facing API using API gateway or using the SDK plugins.
We will invoke one lambda from another via python AWS SDK and boto3 plugins in the example.
Below image shows the different ways of connecting the fleet of lambda’s externally either via API gateway, SNS(simple notification service) or event based S3 invocations.
For our use case, there will be only single API endpoint which will be external and based on the incoming request, it will be propagated to the DB layer lambda complete the functionality.
We will be using the AWS SAM framework to maintain a single cloud formation stack (YAML based) for maintaining and integrating the lambda’s with API gateway and ensuring the lambda’s has specific roles to execute the functions and access the particular service.
Below is the SAM template which is used to maintain and release the functionality.
It contains the clear separation of the Lambda functions based on the usage on the whole architecture.
In the below picture, there are 2 method’s which are exposed via API gateway and they are tagged to the Lambda’s to accept the incoming request. Rest of the Lambda’s are only declared to be created in cloud and cannot be accessed externally(unless the client knows the ARN of the same and has IAM keys to the account)
For our use case We have the luxury of making some requests async(does not have to wait for the invocation to be completed) and for some we have to wait for the request.
Once the functions are hosted in the cloud, each of the lambda will have an unique ARN.
For e.g.: saving the task lambda contains the name – arn:aws:lambda:<region-name>:<account-id>:function:<applicationname>-savetask-<uniqueid>
This is the generic and automated way to generated lambda ARN.
Since,we are aware this function will be responsible for only storing and we are not concerned about the any return response. We will keep the invocation type as “Event”
If we want to get the response and parse the same,we need to keep the invocation type as “RequestResponse”. Below is the example for getting the task result.
There is another type of invocation – Dryrun to perform the check if access is granted to invoke the other lambda.
In this way, we can invoke the business layer lambda from the front facing lambda’s. Once the request moves to business layer, we will be implementing the validations as per the ask of the same. Lastly, the final request to persist in the DB and invoke the lambda to save.
Lastly, in the DB layer lambda function we will be using the pymysql python plugin to save the data in the Aurora DB.
Also,we will be saving the whole SQL which is dynamically generated and now of rows impacted in the DynamoDB for tracing purpose.
Similarly retrieve the data,we will invoke the lambda for retrieving the data from the DB using same pymysql plugin for python.
We showcased the serverless framework for AWS to create a microservice based architecture. There can be many modifications which can be introduced keeping this architecture as a baseline. For e.g.: We can introduce the CloudWatch SDK to consume the metrics and logs from each lambda to create a custom centralized logging and monitoring dashboard. Also, we can add a cache layer in front of the DB to reduce the transactions in the Database and faster response times.
Pros and Cons for this architecture are:
- Faster Development and testing for functionalities.
- Less or zero dependency on infrastructure.
- Easy to integrate other cloud services.
- Flexibility to create more decoupled functions
- Response time are faster compared to other frameworks(excluding pre warmup times)
- Logging and Monitoring might be difficult.
- Limitations of AWS Lambda’s might cause disruptions in the implementation.
- Though it is light weighted compared to other frameworks like Java Spring boot, there can be a situation where we have tradeoff on the memory intensive use cases.