Making a Microservice Architecture Roadmap
In this tutorial we are going to see one of the solutions to boost the application flexibility and scalability is to follow a flexible architecture like that of a microservice-based architecture.
Nowadays, with the rise of social media, fast internet, etc., the tendency to use applications is getting more and more. As a result of these behavior changes, monolithic applications need to deal with a tremendous majority of changes.
Most of the businesses face a new feature that should be added to their application, on the other side, the amount of data that should be processed is getting much higher and in so many cases monolithic applications because of their drawbacks such as slow development velocity, slower deployment, as barely support the agile methodology which is the main idea to deal with fast changes in the software industry.
If you want to create a software project for a big or complex business (It’s not true about startup projects or those projects in the funding stage, because they have to be submissive to the time to market limitations), it’s better to start with microservice architecture.
So, one of the solutions to boost the application flexibility, scalability, and so many other concerns is to follow a flexible architecture like microservice-based architecture.
As I understand so many developers, want to know how they should start this journey, obviously, there are thousands of resources that can be used, but the problem is the dispersion of resources. I decided to make this journey more clear by defining a road map for this learning curve.
A microservice-based architecture has several discrete units which they work together to receive and process requests from various sources. Some parts of this complex can be plug-in units, which means in case of need either you can plug a new unit or unplug a unit, which shouldn’t disturb the overall work of an application.
For example, if you have decided to implement a microservice architecture, you should be familiar with various concerns in a life cycle of an application such as persistence, logging, monitoring, load balancing, caching, etc. besides you should know which tools or which stack are more suitable in your applications.
Well, this is the main approach of my article: I will explain the concern, then introduce some of the best tools for satisfying the needs.
I explain each topic to get answers to these questions:
- What is it?
- Why should I use it?
- Which tools are better?
Notice that I have mentioned for tools part just two or three tools, Of course, we have so many other tools, the criterion for choosing these tools is popularity, performance, being open-source, and also update frequency.
Notice again, we have also cloud-based services which are out of the scope of this article to be discussed.
I have used the above diagram as the architecture diagram sample, because this diagram involves most of the microservice architecture components and also has been recognized as a standard model, of course, I know this diagram is not a very comprehensive diagram, but I have tried to keep this article as simple as possible, maybe in future I would revise the article and write a new version of that. I think the best mindset about explaining every concept, should always follow the KISS pattern.
The concepts which have been explained in this article are:
- Container orchestration
- Docker container management
- API gateway
- Load Balancing
- Service discovery
- Event Bus
- Monitoring And Alerting
- Distributed tracing
- Data Persistence
- Cloud Provider
Docker is an open-source platform for containerizing your applications, with the libraries, and dependencies that your application needs to run in various environments. With the help of Docker, development teams are able to package applications into containers.
Actually, Docker is one of the tools to containerize applications, Which means you are also able to create containers without using Docker, The real benefits of Docker are to make this process easier, safer, and much simpler.
After you containerize your application, you will need some tools for managing containerized applications for doing some manual and automated operations like horizontal scaling.
These tools provide some services for your application management like automated load-balancing, guarantee high service availability.
This kind of service is done by defining several manager nodes, and in case of any failure in one node manager, the other managers can keep the application services available.
Kubernetes or K8s ,Docker Swarm
Managing Docker environment, configuration management, and providing the environment security, etc. These concerns can be centralized and automated by a docker container management tool.
A Docker container management tool provides a GUI-based tool for users, and they do not have to deal with CLI which is not comfortable for all users. These tools give developers a rich UI to build and publish their images, also make it much easier to do some operational tasks such as services horizontally scaling by providing a simplified user interface.
Portainer, DockStation, Kitematic, Rancher
An API gateway can be considered as an API management tool that works as a middleware between your application services and different clients. An API gateway can manage many things such as:
- Routing : A gateway receives all API requests and forwards them to the destination services.
- Logging : You will be able to logs all the requests in one place.
- Authorization: Check if you are as a user are eligible to access the service or not, if not the request can be short-circuited
- Performance profiling: You can estimate every request execution time and check your application bottlenecks.
- Caching: With handling your caching at the gateway level, you would eliminate so much traffic on your services.
In fact, it works as a reverse proxy, and clients just need to know about your gateway, and application services can be hidden from the outside.
Without an API gateway, you may need to do some cross-cutting concerns in every service, for example, if you want to log the request and response for services. Besides, if your application consists of several services, your client needs to know about each service address, and in case of changing a service address, several places should be updated.
One of the most important reasons that we have chosen the microservice architecture is scalability, Which means we will be able to handle more requests by running more instances of our services, but the question is, which instance should receive requests or How do clients know which instance of service should handle the requests?
The answer to these questions is Load Balancing. Load Balancing means sharing the income traffic between a service instance.
In order to scale your independent services, you need to run several instances of the services. With a load balancer, clients do not need to know the right instances which serving.
Traefik, NGINX, Seesaw
As your application services count getting more and more, services need to know each other service instance addresses, but in large applications with lots of services, this cannot be handled. So we need service discovery which is responsible to provide all components addresses in your application, they could easily send a request to the service discovery service and get the available services instance address.
When you can have several services in your application, service discovery is a must-have for your application. Your application services’ don’t need to know each service instance address, it means service discovery paves this way for you.
Consul, Zookeeper, Eureka, etcd and Keepalived
In microservice architecture pattern, you would use two different types of communication, Sync and Async communication. Sync communication means services call each other through HTTP call or GRPC call. Async communication means services interact with each other via a message bus or an event bus, It means there is no direct connection between services.
While your architecture can use both communication styles simultaneously, for instance in an online shop example you can send a message whenever an order is registered and those services which have subscribed to a specific channel will receive the message. But sometimes you may need some real-time inquiry, for instance, you need to know the quantity of an item, you may use GRPC or HTTP call between services to get the response.
If you want to have a scalable application with several services, one of the principles you would follow is to create loosely coupled services that interact with each other through an event bus. Also, if you need to create an application that is able to plug in a new service to receive a series of specific messages, you need to use an event bus
When using a microservice architecture pattern it’s better to centralize your services logs. These logs would be used in debugging a problem or aggregating logs according to their types for analytical usages.
In case of any need to debug a request, you may face difficulty if you do not gather services logs in one place. You are also able to correlate the logs related to a specific request with a unique correlation Id. It means all logs in different services related to a request will be accessible by this correlation Id.
In a microservice architecture, if you want to have a reliable application or service you have to monitor the functionality, performance, communication, and any other aspect of your application in order to achieve a responsible application.
You need to monitor the overall functionality and services health, also need to monitor performance bottlenecks, and prepare a plan to fix them. Optimize user experience by decreasing downtime of your service by defining early alerts for your services in critical points. Monitor overall resource consumption of services, when there are under heavy load and etc.
Prometheus, Kibana, Graphana
Debugging is always one of the developers’ concerns, As you, all have the experience to trace or debug a monolithic. It’s very straightforward and easy, But when it comes to microservice architecture, because a request may be passed through different services, which makes it difficult to debug and trace because the codebase is not in one place, so here distributed tracing tool can be helpful.
Without a distributed tracing tool it’s frustrating or maybe impossible to trace your request through different services. With these tools, you can easily trace requests and events with the help of having a rich UI for demonstrating the flow of the request.
OpenTelemetry, Jeager, Zipkin
In most systems, we need to persist data, because we would need the data for further processes or reporting, etc in order to persist data, we need some tool to write our application’s data into a physical file with a different structure.
In monolithic applications, we used to have one or two different persistence types and most of the monolithic applications use Relational databases like SQL Server, Oracle, MySQL. But in a microservice architecture, we should follow the “DataBase per service” pattern, which means keep each microservice’s persistent data private to that service and accessible only via its API.
Well, You would have different databases for different usages and scenarios. For instance, a reporting service might use NoSQL databases like ElasticSearch or MongoDB because they use document base structure, It means the structure for persisting data in these databases is different from relational databases, which are suitable for services with a high rate of reading or fetching data.
On the other hand, you may need relational databases like Oracle or SQL SERVER in some microservices or you may also need some databases which support graph structure or key-value structure.
So, in Microservice architecture, according to the service mission, you would need different types of databases.
Relational databases or RDBMS : PostgreSQL, MySQL, SQL SERVRE, Oracle NoSQL database : MongoDB, Cassandra, Elasticsearch
Caching reduces latency in service-to-service communication of microservice architectures. A cache is a high-speed data storage layer that stores a subset of data. When data is requested from a cache, it is delivered faster than if you accessed the data’s primary storage location.
In a microservice architecture, there are many strategies in which caching can be implemented in those ways. Consider the following:
- Embedded Cache (distributed and non-distributed)
- Client-Server Cache (distributed)
- Reverse Proxy Cache (Sidecar)
In order to reduce latency, caching can be implemented in different layers. It means you would have a higher response time. besides, you can also implement distributed caching which is accessible for several microservices and sometimes considered as a placeholder for shared resources, which have different usage, like Rate-limiting, which is the most common reason for rate limiting is to improve the availability of API-based services by avoiding resource starvation.
Redis (REmote DIctionary Server), Apache Ignite, Hazelcast IMDG
A cloud service provider is a third-party company offering a cloud-based platform, infrastructure, application, or storage services. Much like a homeowner would pay for a utility such as electricity or gas, companies typically have to pay only for the number of cloud services they use, as business demands require.
Most important categories for cloud providers:
- Software as a Service (SaaS).
- Platform as a Service (PaaS).
- Infrastructure as a Service (IaaS).
One benefit of using cloud computing services is that firms can avoid the upfront cost and complexity of owning and maintaining their own IT infrastructure, and instead simply pay for what they use when they use it. Today, rather than owning their own computing infrastructure or data centers, companies can rent access to anything from applications to storage.
Amazon Web Services (AWS) , Microsoft Azure, Google Cloud, Alibaba Cloud