Two years ago, I wrote my yet most popular blog on microservices vs monolith The aim of the blog was to introduce my readers to the advantages of microservice architecture and how that compares to a monolith architecture. While there has been a lot of growth in adoption of microservices recently, there is still big knowledge gaps on how to design your architecture, decoupling already existing monolith application, deploying and monitoring of applications among others.
In this blog, I will guide you through some of the considerations you need to make before shifting to microservice architecture using some simple application that I developed using Nodejs and MongoDB.
The code is available on my Github repositorywhich you can clone follow through the blog and even modify to your liking.
There are three microservices and each has its own collection (database) and can operate independently. The microservices are based on subdomains around the concept on an e commerce platform.
Download/ clone the code from GitHub git clone https://github.com/wbenmurimi/microservices.git
Manually
Update the database connection by updating the variable DATABASE_URL on all the .env files in the app folders. You can use locally hosted mongodb or configure a free mongo atlas cluster for testing.
Install the node_modules in each of the applications by running npm install
Run the server nodemon serve
Interact with the api via postman/equivalent API testing tool
Docker
With this approach ensure that you have docker installed. Update the database connection by updating the variable DATABASE_URL on all the .env files in the app folders. You can use locally hosted mongodb or configure a free mongo atlas cluster for testing.
Create docker images for each microservice. Note the [.] at the end. It means create the container from the content in the current directory. Otherwise you can also provide relative or absolute path to the project folder.
docker build --no-cache --rm --tag users:v_1 .
docker build --no-cache --rm --tag products:v_1 .
docker build --no-cache --rm --tag orders:v_1.
Run the docker images. Note that the port numbers here are the ones that you have exposed in the Dockerfile. If you change either make sure they are the same including on the API endpoint
docker run --rm -d -p 3000:3000 users:v_1
docker run --rm -d -p 3001:3001 products:v_1
docker run --rm -d -p 3002:3002 orders:v_1
Interact with the API via postman/equivalent API testing tool A couple of docker commands you can use to interact with docker containers are;
List running containers docker ps -a
Show the logs of the running container
docker logs [container_id]
Stop a running container
docker stop [container_id]`` ` Start a container
docker start [container_id```
API ENDPOINTS
GET http://localhost:3000/api/users/ Get all the users
POST http://localhost:3000/api/users/register Register a user
{
"name": "My User",
"email": "[email protected]",
"password": "myuser"
}
POST _http://localhost:3000/api/users/login _Login a user
{
"email": "[email protected]",
"password": "myuser"
}
GET http://localhost:3001/api/products/ Get all products
POST http://localhost:3001/api/products/ Create a new product
{
"name": "Bread",
"cost": "1,200"
}
GET http://localhost:3001/api/products/{id} Get a product with a given id
Product id
GET http://localhost:3002/api/orders Get all orders
Bearer JWT token
POST http://localhost:3002/api/orders Create an new order
{
"product": "5e7dee2e495a5c42a3460656"
}
Bearer JWT token
Interact with the API as documented above and do not forget to set the correct headers [Content-Type and Accept headers should be application/json for all API calls]. Start by creating a user and then login.
Take note of the JWT token returned as shown in the screenshot below. Note that the token is only valid for one day after generation. For further API calls on the order microservice you will need to generate another token.
Create products using the API. When you list the products, take note of one product ID that you can use to create an order.
To interact with the orders microcervice, you will need to use the JWT token returned when you authenticate to the users microservice as shown in the screenshot below.
There are a dozen approaches that you can use to change your monolith application to a microservice. Below are some approaches that I recommend.
Separate Backend and Frontend: If the frontend is still part of your application, separate them into different services. This means the backend will expose APIs that will be consumed by the frontend. At this stage, you should not focus on re-writing your application just utilize existing code base and keep it simple. Some of the frameworks you can consider for the frontend include angularjs, reactjs and vuejs.
Stop making the monolith bigger: Most often extending and managing monoliths become a complex task the bigger it gets especially when adding new features. This approach means that when you are implementing new functionality you should not add more code to the monolith. Instead, the idea is to put that new code in a standalone microservice. This new microservice could function by making API calls to the mother monolith application or accessing monolith’s DB directly. This is a good step towards later decoupling the monolith as described below.
Decouple the Monolith: This approach involves picking modules from the monolith and developing one after the other while still maintaining and using the monolith code. One of the common pitfalls is attempting to re-write everything from scratch. With a new architecture and a steep learning curve, it is always a good idea to avoid this move especially for production applications. Here are a couple of things to guide you on which module you should start with;
Here are some tips you should follow to ensure a successful transition from a monolith to a mmicroservice architecture.
I’m always an advocate of “lazy decoupling” meaning that even though the end goal is to have independent and highly manageable services, the more services you end up with the more difficult it is to manage and even debug when things aren’t working fine. Reducing the number of services also means you will be making fewer API calls between the services which will improve the performance of the applications.
While one of the benefits of microservices is being able to write them in different programming languages, do not go that route at the beginning. Having one stack for your services improves interoperability, is easier to manage and update and makes it easier to re-use components hence quick development.
Services must be cohesive. A service should implement a small set of strongly related functions. This builds on the principle that things that change together should be packaged together to ensure that each change affect only one service.
Reference:
To make a comment you have to login
0 Comments