Understanding Monolithic and Microservices Architecture
In this article, we will try to understand the Monolithic and Microservices architecture in terms project team, analysis/design, development/construction, continuous integration /deployment and testing.
1. Monolithic Architecture
Before jumping into Microservices, let's see what is Monolithic architecture. Let's say you are building an application that has following basic services for a shopping website having services like Customer Service, Product Service, Inventory Service, Payment Service, Shipping Service
The above monolithic architecture has following benefits:
- Developing using specific technologies quiet simple, it is not much complex to develop.
- Deployment is simple
- Consistency can be maintained
- Refactoring is easy
But as the application becomes large and complex, then things becomes challenging as below
- Application maintenance becomes challenging over the time period in terms code change impact and fixing bugs
- Developer productivity - With large code base, productivity of developers becomes slow
- Continuous integration and deployment -Risk associated with redeployment increases
- Scaling- one can scale with an increasing transaction volume by running multiple copies of the application but this architecture can’t scale with an increasing data volume.
- CPU/memory Consumption- Each application components will have different resource requirement in terms I/O traffic, CPU and memory. Scaling each component independently is not possible
- Monolithic architecture forces one to stick with a particular technology stack. Its not easy to replace component based on some new technology stack
In a nutshell, a monolithic application puts all or most of its functionality in to single process and scales by replication on multiple servers and its hard to keep modular structure. Codebases grow as we write code to add new features. Over time, it can be difficult to know where a change needs to be made because the codebase is so large. The golden rule, can we make a change to a service and deploy it by itself without changing anything else? If the answer is no, then its time to revisit the architecture.
2. Microservices Architecture
In microservices architecture, each element of functionality is put into seperate service. Then these services are scaled across different servers and replication depending on I/O traffic, CPU and memory requirements. Lets try to understand some of the characteristics of microservice architecture
2.1 Separate components into services
Here definition of component is "a unit of software that is independently replaceable and upgradeable".
One point to be noted here is when we say :
- Libraries as components then they are called using in-memory function calls
- Services as components then they are out of process components which communicates using web service or remote procedure calls.
Using services as components ,rather than libraries, is that services are independently deploy able. Lets say an application with multiple libraries in a single process, change in in any single library results in to deployment of entire application. But if that application is decomposed into multiple services, you can expect many single service changes to only require that service to be redeployed.
Remote calls are more expensive than in-process calls, and thus remote APIs need to be coarser-grained, which is often more challenging to use. If you need to change the allocation of responsibilities between components, such movements of behaviour are harder to do when you're crossing process boundaries.
2.2 Organize team based on business capabilities not technology stack
Normally in project, team is divided into UI ,Client side ,Server side and database team. The challenge here is that even for simple change impact is on multiple teams which leads approvals etc. The microservice approach is to split the teams based on business capabilities may be like Customer, Payment, Shipping etc.This leads to the teams are cross-functional, including the full range of skills required for the development.
2.3 Product Model
In most application development, we use project model where some functionality of software is delivered and when it is deployed in production after that it is handed over to production support team. Microservice do not recommend this model, instead a team should own a functionality/product over its full life time.This brings development team to work closely with users of the application.This will make development team to understand and assist its end users to enhance the business capability.
2.4 Data Management should be decentralized
Monolithic applications prefer a single logical database for persistent data across a range of applications. Microservices prefer letting each service manage its own database, either different instances of the same database technology, or entirely different database systems.
Decentralizing responsibility for data across microservices has implications for managing transactions to guarantee consistency when updating multiple resources.2.5 Automation
Microservices add a lot of complexity as we have to deal with lot of moving parts. Automated testing, continuous integration and deployment of individual services ensures our services still works as more complex process than with monolithic systems.
2.6 Design for failure
Impact using services as components, is that applications need to be designed so that they can tolerate the failure of services. We need to check for circuit breakers as mentioned below :
- Make sure your timeouts are set appropriately.
- When using network calls you are prepared for different sorts of failure mode and expect failure will occur anywhere and everywhere
- Understand what the customer-facing impact will be if only one part of the system is misbehaving.
- implications of a network partition might be, and whether sacrificing availability or consistency in a given situation is the right call.
Since services can fail at any time, it's important to be able to detect the failures quickly and, if possible, automatically restore service. Microservice applications put a lot of emphasis on real-time monitoring of the application.
2.7 Hide Internal Implementation Details
To maximize the ability of one service to evolve independently of any others, it is vital that we hide implementation details.Consider using REST, which formalizes the separation of internal and external implementation details
2.8 Some Prerequisites for microservices
Good Understanding of Domain:
Less well one understand a domain, the harder it will be for to find proper bounded contexts for the services.Getting service boundaries wrong can result in having to make lots of changes in service-to-service collaboration which makes an expensive operation
One should be able to fire up a new server in short time.To be able to do such rapid provisioning, one need a lot of automation.
Sticking with old monitoring practices where you just look at stats like CPU and memory may not be sufficient as more service-to-service collaboration with many loosely-coupled services collaborating in production,Things are bound to go wrong in ways that are difficult to detect in test environments.
Rapid application deployment:
with many services to manage, you need to be able to quickly deploy them, both to test environments and to production.
Good Service design i.e. loose coupling and high cohesion:
When services are loosely coupled, a change to one service should not require a change to another. The whole point of a microservice is being able to make a change to one service and deploy it, without needing to change any other part of the system.On other side , We want related behavior to grouped together so that communication with other boundaries are as loosely as possible and unrelated behavior to be grouped elsewhere.
3.0 Comparison Monolithic and Microservice
|Simplicity||Easy to simple to use||Complex - Distributed computing and Asynchronous communication|
|Partial Deployment||Upgrade one component, you needs deploy whole or at least major components||Ability to deploy various components independently Deploy applications more frequently|
|Availability||Many or whole application goes down||One service goes down, still one can run your application|
|Consistency||Consistency can be maintained||One may loose consistency for high availability|
|Refactoring||Refactoring is easy .||Need to revisit the design. To consider remote calls, need to understand module boundary otherwise refactoring will be challenging.|
|Preserve Modularity||As application becomes complex and big, preserving modularity becomes challenging||Help preserve modularity|
|Multiple platforms||It becomes challenging to work on multiple platforms.||As various components independently,allows use of multiple platforms like Java services, WCF .|
|Scaling||Scaling the application can be difficult.T his architecture can’t scale with an increasing data volume.||Easier to scale development and enables you to organize the development effort around multiple teams|
|Fault Isolation||One misbehaving component can bring down the entire system||If there is a memory leak in one service then only that service will be affected. The other services will continue to handle requests|
|Technology Stack||Its not easy to replace component based on some new technology stack||Eliminates any long-term commitment to a technology stack|
|Testing||Testing is easy comparatively||Testing is more challenging|
|Inter-Service Communication||As services are mostly running on same processes, comparatively less inter-service communication mechanism is required||As services are distributed and running on different processes, one must implement the inter-service communication mechanism|
|Distributed transactions||As services are mostly running on same processes, comparatively less distributed transaction mechanism is required||As services are distributed and running on different processes, one must implement the distributed transaction mechanism.|
Despite some positive experiences, it is not certain that microservices are the future direction for software architectures.One needs to consider following points before moving to Microservice architecture:
- Challenge in deciding boundaries across different service.
- Refactoring is difficult across boundaries that in-process libraries
- Testing is more complicated
- Consider factor of team skill to adopt new techniques
1) Microservices by martin Fowler : http://martinfowler.com/articles/microservices.html
2) Microservices Pattern : http://microservices.io/patterns/microservices.html
3) Book: Building Microservices by Sam Newman