Microservices Architecture: What, When, and How
Introduction
The microservices architecture pattern is getting a lot of attention these days and it’s trending. If it is hard to believe, then just check what Google Trends says.
You can see a big spike of interest over this term, starting in 2014, and the trend keeps on increasing as time passes.
This hype (microservices) is at the peak of inflated expectations in the Gartner Hype Cycle model.
It is worth studying the microservices architectural style even when it is at the peak of inflated expectations. I believe there is a moderate risk associated with it and it would be good to spend time to understand it. As of now, it seems very promising.
You may also like: Microservices in Practice: From Architecture to Deployment
There are some strong points which favor this hype. Several big companies like Netflix, Amazon, and others have talked about the way they scaled and ease out the continuous delivery of their services using a microservices architecture.
Microservices architecture design doesn’t seem to be a buzz to ignore. This architectural framework is the core selling point for emerging startups like Docker, CoreOS, Infrastructure as a Service (Cloud Computing), and others.
These new products are easing out the development and deployment effort for microservices architecture based applications.
Docker is an open-source container technology, which enables us to deploy several self-contained isolated applications (or services) on single Linux OS as they are running in their OS environment. It has seen a huge growth in the past year and its major sponsor Docker Inc. has been valued more than $1 billion while getting fundings.
I believe there are enough reasons to have a comprehensive analysis of this architectural framework.
In this article, we will talk about the microservices architecture style in detail. We will try to answer the following questions:
- What is it?
- When should it be used?
- How should we use it?
What Is it?
A microservices architecture makes more sense when we compare it with monolithic application design.
In monolithic architectural design, we create a big cumbersome application with all modules tightly coupled inside a single executable, which is typically deployed on a web or application server.
A typical monolithic architecture application looks like:
There are some disadvantages to this architectural design. These disadvantages or drawbacks have become the strengths of microservices architecture:
- No frequent and easy releases — As monolithic applications grow in size, due to tight coupling between components, it becomes difficult to do easy and frequent releases. Release planning takes a lot of time of people from various groups. The frequent release is discouraged for making sure the application should not break due to the newly released feature.
- The problem in continuous delivery — We may not notice this problem if the application is small. In the case of bigger monolithic applications, deployment times can be frustratingly long and slow. If a single change to the application would require the entire application to be redeployed, then this could become an obstacle to frequent deployments, and thus an impediment to continuous delivery. This could be a serious issue if you are serving a mobile application where users expect the latest cool new features all the time.
- Difficult to manage team and project — Project management has its challenges in monolithic application development. Even a modularized application has interdependency in terms of deployment and release. It takes a toll in terms of time and effort to plan the release and manage tightly coupled interdependent modular development.
- Expensive scalability and performance — It is possible to scale a monolithic application but the cost is very high.
- Lack of technology diversity — When we choose a technology stack for a monolithic application, we consider a balanced stack that can serve well for all of our requirements. We can not employ specific technology for specialized needs.
- Not easy to replace components — It is very difficult to replace any component with a better design or performance without affecting the whole architecture.
Definition
In short, Microservices architectural style defines a setup, where application components are standalone applications of their own. These independent application components talk to each other either using RMI (Remote Method Invocation), Restful Web Services or Push Messaging.
A typical Microservices based application setup is given here:
While designing systems in microservices architecture, we should be identifying independent components/modules appropriately. These components will be mini-applications, which will be developed separately. They will follow their development and deployment lifecycles.
Consider we are developing one school management system. In a school management system, we have various important components like student registration, attendance, fees, assessments, etc.
When we develop this application using microservices architecture we will have independently deployed mini-applications for student registration, attendance, fees, and other modules.
In a general setup, we can have scenarios where we need data from various components for a single request. Ideally, we will have an API gateway or front controller which will aggregate data from these components and give it back.
We should have inter-component communication. Components can communicate over REST APIs or Messaging or RMI (Remote Method Invocation).
Characteristics of microservices architecture based application are as follows:
- Service enabled, independently running components.
- Independently running components classified around some business capabilities.
- Product mentality over the project.
- Smart components using simple communication channels like simple RESTish protocol or lightweight messaging queue.
- Decentralize standards. Each independent component can use its exclusive standard for development and deployment.
- Decentralized data management. Observe in the above diagram, how individual components have their own data storage.
- Automated infrastructure management. For the deployment of independent components, we need to rely on automated infrastructure management to reduce complexity.
- Application design considering failure in mind. There are several independent moving parts in applications. In the event of the receiver not getting a response, it should be handled gracefully.
- Evolutionary design for getting the best possible decomposed system, which can be replaced and upgraded without affecting its collaborator.
Bad Parts
Every coin has two sides, similarly, Microservices Architecture has its own set of problems. We have seen the good parts of it so it would be useful to also take a closer look at its bad parts.
There are some drawbacks or additional work, which we find in the Microservices Architecture based application:
- Team communication overhead — Microservices architecture reduces team management complexity, but it is not able to diminish the need for team communication. Teams need to make sure that updates in one team's service do not break another's team functionality. We find this problem in monolith architecture applications, too.
- Formal documentation overhead — Every individual running a component application needs to keep updated schemas and interface documents all the time. It helps other teams who are using the service.
- Non-uniform application — We can choose a different technology stack for different components (polygot). It leads to a problem of non-uniform application design and architecture. It can increase maintenance costs in the long run.
- Dev-Ops complexity — We need to have a mature DevOps team to handle the complexity involved in maintaining microservices-based applications. Due to several moving parts of the application, it becomes complex and requires a level of expertise.
- Increased resource use — Initial investment to run these applications is high because all the independently running components need their runtime containers with more memory and CPU.
- Increase network communication — Independently running components interact with each other using the network. Such systems require reliable and fast network connections.
- Marshalling and unmarshalling — When one component needs data from another component, the sender marshals the data in some standard from its internal representation, while the receiver unmarshals data in its representation before use. This requires more processing in comparison to conventional application architecture.
- Network security — Inter-service communication needs to be secured to avoid any security breach. Due to several moving parts, these applications are more prone to security vulnerabilities.
- Testing — Testing such applications is harder in comparison to monolith applications.
- Production monitoring — Cost to monitor such applications is higher. Unavailability of the right tools is also an issue to be considered.
- High upfront cost — Running multiple applications will incur more cost in comparison to monolith applications.
All the issues we had mentioned above can be solved with extra effort or usage of adequate tools. Monolith applications are also prone to a few issues mentioned here.
In the next section, we will talk about the use cases in which we should be using a microservices architecture. Let's also try to answer the question — When & how should we use microservices architecture?
When and How Should We Use It?
If we try searching Google about the adoption of this architecture, we can see several articles floating around on the successful implementation of it. Some of the products and companies who had implemented it:
- Netflix (Ref)
- eBay (Ref)
- Amazon (Ref)
- Several other large and medium technology product companies
We should use a microservices architecture for any product/project in these two approaches:
- Monolith only or monolith first approach
- Microservices first approach
Monolith Only or First Approach
All the mentioned companies had lately changed their application from a monolith to microservices architecture. While in the beginning, they started as monolith applications, they have steadily moved/converged to microservices. Hence, it makes us ponder whether Microservices might be more suited to applications, which are very large and complex.
We should be opting for monolith only or first approach in the following circumstances:
- Business is not ready to invest in the upfront cost that microservices-based applications incur.
- The inability of the business to foresee the value provided by the microservices first approach.
- Unavailability of suitable manpower to build and run microservices-based applications.
- Software delivery with tight time constraints: Sometimes monolith helps in entering the market very quickly.
- When the state of tools and technologies available to support the smooth deployment of the microservices application, is a concern.
Keeping the above pointers in mind will help in deciding when to use monolith only or the first approach.
Though it’s hard to deny the fact that microservices applications are the ideal to follow, we must see the trade-offs. Typically when a monolith application becomes successful or needs serious help for scale and performance, we may opt for microservices. We can opt for microservices in two ways:
- Extend the well designed modular components from the monolith — Usually, we find business people supporting monolith first design, thinking it will be easy if required, to convert a modularly designed, monolith application to microservices at a later stage. They opt for a modular monolith application, to reduce the cost they may incur to develop microservices should the need arise. But this is a distant dream, often far from reality.
- Recreate the microservices application from scratch and dump the existing monolith application — Most of the time microservices applications are developed from scratch because of bad modularity in monolith applications.
Microservices First Approach
When we start developing applications we always wish to keep them modular. Each module should have a distinct set of responsibilities. We try to do so to reduce the complexity of applications in the hope of achieving extensionality and maintenance.
I think if modularity is the prime reason to opt for microservices, then why should this not be a possibility in monolith applications? After all, we can have it in monolith applications too.
What we expect from an application in terms of modularity and what we get is demonstrated in this illustration:
I think the answer lies in the way we develop software and how it grows from a small piece to a very large chunk. In monolith applications, we are always tempted to develop things very quickly and we get the opportunity to do so because there is no hard boundary defined, and while churning things quickly, we lose its modularity. In the long term, these overlapped modular functionalities kill team productivity and we face a hard time optimizing and scaling applications.
Even idle modular monolith applications will have a centralized database for all of its modules.
I believe if we try to find out one idle modular monolith application in production, it will be very difficult for us.
Microservices applications have decentralization as their core concept and it provides a hard line between modules along with decentralized data storage. By design, it is difficult for developers to cross the line and it helps in enforcing real modular application. The result gives us benefits, which have already been mentioned.
We should, therefore, be opting for the microservices first approach when:
- Modularity and decentralization is an important aspect from the beginning of any project.
- The application in focus will have high volume transactions or traffic.
- Preference for long term benefits in comparison to those in the short term.
- Availability of the right set of people to design, develop and deploy applications quickly in the initial phase — It has been observed that the initial effort to start a microservices-based project is more in comparison to a monolith one.
- Commitment to using cutting edge tools and technologies — Microservices are very young architectural approaches; tools and technology required to support it are very new or in rapid change mode.
Conclusion
The microservice architecture is not a new approach; its soul was always there for years in the form of SOA (Service Oriented Architecture), web services, and in a modular and layered architecture.
It is gaining momentum primarily due to the following factors:
- Frustration at not getting the desired output expected from architecture like a monolith.
- Availability of tools and technologies to develop and deploy microservices applications with ease.
- Wide adaptation of Infrastructure as a Service (IaaS), like Amazon Web Services, Google Cloud Platform, or others, that have opened the door for easy DevOps operations.
- Big technology product company adaptation for microservices architecture.
In the coming years, It will be no surprise to see it growing at a level in which software engineers will be using monolith for just prototyping. Who would not want to have a modular, highly performing and easy to scale application in the deployment in the time of the Internet of Things?
References
- Microservices articles by Martin Fowler
- Don’t Start With Monolith
- Building Microservices: Inter-Process Communication in a Microservices Architecture
- Nginx Introduction to Microservices
- Building Microservices by Sam Newman
- Microservices Wikipedia
Further Reading
Microservice Architecture — Learn, Build, and Deploy Applications
What Are Microservices? An Introduction to Microservice Architecture