Multi-Module Monolithic as Microservice
There are many discussions we are finding over the internet about microservices and monolithic architecture.
Join the DZone community and get the full member experience.
Join For FreeThere are many discussions we are finding over the internet about microservice and monolithic architecture. Its advantages and disadvantages consideration by looking at technology, team size, architecture expertise, efforts, maintainability, delivery on time and project budget.
Let's try to simplify and differentiate between actual requirements from a business perspective which can be achieved by application architecture and deployment architecture.
Problems in Monolithic Architecture
Business Operations Are Used at Different Frequency and Impacts Are
- Heavy operations are using more resources and affecting other operations and eventually the whole system. Scaling for heavily used operations is needed.
- Less frequently used operations are consuming resources, therefore cost.
Problems of Technical Implementation
- Domain level boundaries are not separated by constrains in a monolithic application, hence it leads to complex and unmanaged code
- Adopting new technology in the larger application is difficult.
- The single-component change will require to build the whole application.
- The whole application will go down just to deploy changes in a single component.
- The startup time of the application is high as it will load all modules.
Let's describe monolithic, microservice and the Multimodal Monolithic as Microservice:
Monolithic: Single/Multiple monolithic instances are running to serve all the operations.
Microservice: Single/Multiple microservice instances are running and API gateway is configured to serve specific operations to the responsible microservice domain.
Multimodule Monolithic as Microservice
- Deployment architecture — The Monolithic instance is running, but it serves a specific business operation. Here business operation may involve multiple module interactions, which happens within a single monolithic instance. Hence scalability can be achieved at a business operation level instead of a specific domain level.
- Application Modular architecture with domain boundaries — To define module boundary within an application, the application uses libraries and multiple module projects to solve a specific business problem.
- Example. An Application with Order and credit card services. Two monolithic instances are running each one to serve order and credit card services respectively. These are done by configuring the API gateway to redirect traffic of orders and credit cards to a single instance at a time. If any business operation like order execution checks the credit card balance first, it will be executed as a single business operation within the single monolithic instance.
The below table includes a few challenges and solutions when the application is following one of the above architecture.
Item
|
Description | Monolithic Architecture Problems | Microservice | Multimodule Monolithic as Microservice |
Services |
Heavy operations are using more resources and affecting other operations and eventually the whole system. Scaling for heavily used operations is needed.
|
Application memory and CPU consumption are high due to heavy operations and more traffic. The application can not restrict resource consumption for specific operations. | Services are developed to the server the specific domain operation and running as a separate process with a dedicated allocation of resources to each microservice. To fulfill a single business operation, it may require multiple microservice involvements. |
✌ Services that demand high resources due to heavy computation or traffic are running as a separate process but as a monolithic application. Each monolithic instance is serving a specific business operation. Hence all the operations are allocated dedicated resources to serve high availability with smooth performance. Each monolithic instance is responsible to serve specific services and this is achieved by allocating dedicated resources without breaking application code into microservices. |
Less frequently used operations are consuming resources, therefore cost. | Application modules with less usage frequency are loaded and consuming resources even being ideal for most of the time. | Microservice instance serving specific business operations required to be alive when needed. | Monolithic instance serving specific business operations required to be alive when needed. | |
Communication | Data transfer between different domains needs to be easy and should consume fewer resources. |
Application modules communicate directly to each other. | Sol 1. REST API calls between microservice - Dependent on other microservice, API calls are not as simple method calls, API Standards to be maintained with versioning, Network latency affects the performance and network resources will be consumed. | ✌ Application modules are used by the application. The application communicates directly via public interfaces from modules and makes decisions. Communication is within the application memory is much faster than microservice because REST API calls transmit data from the application to the kernel to network. |
Sol 2. Event-driven architecture can be implemented - Asynchronous calls to be maintained and this is complex, the event store requires more resources, event loss in case of a crash, data transmitted in events to be managed. | ||||
Data conversation and specification. | Extra data format conversation and specification required for REST API or event data. This leads to more communication within the team and consumes resources. | ✌ Not required as a module interface can directly expose data within memory. Data specification can be exposed as source code documentation which is the easiest one. | ||
Transaction | ACID properties are preferred over business operations. | ACID properties are maintained, as the transaction is initiated and completed within a single monolithic instance. | Distributed transaction management is required to be handled across the whole infrastructure and microservices. | ✌ ACID properties are maintained, as the transaction is initiated and completed within a single monolithic instance. |
Database | ||||
Structural aspects | Database/Schema per service to isolate data boundaries or a single database. | Database/Schema per service to isolate data and boundaries or a single database. | ||
Data integrity | Foreign constraints support only in the same database server within the same and multiple schemas. When each microservice has a separate database server using soft references does not maintain data integrity. | ✌ Data integrity always maintained as a separate database server not required. | ||
Application-level data cache | Distributed caching is required for multiple replicas of microservice which manipulate and access the same domain data. | Distributed caching is required for multiple replicas of monolithic instances that manipulate and access the same domain data. | ||
Data Access | Microservice communication required to fetch the data from different microservice at the cost of resource consumption and performance. Ex. Check the remaining credit limit before order execution. The credit limit will be collected from micro service as a separate call. |
✌ No external communication required to access data from other modules as business operations are executed within the same monolithic instance. E.x. To check the remaining credit limit before order execution. The credit limit will be collected from the module public interface as a function call. |
||
ORM - Eager fetching and Relationships | Microservice is responsible for specific domain operations. Other micro service ORM Entities should not be defined across other microservices. Microservice will fetch data as a separate communication call. | ✌ An application that consumes other modules will fetch data as separate public interface calls. The module is responsible for specific domain operations. Other module ORM Entities should not be shared/ definitions across other modules. | ||
REST Security | The REST API defines operation access for other services. Each microservice has to implement pubic private certificate for security or in another way. | Application services are responsible to handle what to execute by maintaining the specification contract of business operation. | ||
Data Security | Within the same database server with/without different schema database user access has to be managed, as data is available to view and manipulate. | Within the same database server with/without different schema database user accessibility has to be managed, as data is available to view/ manipulate. | ||
Application maintenance | ||||
Domain level boundaries are not separated by constrains in a monolithic application. | Code complexity increases as code have no tight boundaries and accessed openly without any constraints. | Boundaries are defined as microservice | The application architecture should be divided into libraries and modules. This will ensure the boundaries across the modules. | |
Technology | ||||
Adopting new technology in the larger application is difficult. | New technology will affect the whole application. | Each microservice can be developed with different technology. But this is feasible only in cases service responsibility is different from others. E.x. All Transactional services are developed in the same technology and framework, while schedulers and reporting services are in other technology | All the interconnected modules (in terms of business aspect) and libraries are in the same technology. A process like schedules, reporting can be separate from monolithic and developed in other technology. | |
Compilation | Failure of microservice incompatibility found only when they communicate. It is easy to identify the impact of change and test impacted areas, but it depends on the quality of the analysis. One solution to this is to maintain SDKs for exposed APIs from microservice, but still, new SDK versions to be distributed and injected in other microservices. | ✌ Module incompatibilities found during compilation itself as all the modules build at the same time. | ||
Deployment | ||||
Build | The single-component change will require to build the whole application. | Version compatibility maintenance required between microservice communication contract. | ✌ The application is shipped as a single war or executable. No version compatibility maintenance between different modules. | |
Deployment | The application will shut down for a while and up again with the latest version. | Single service will go down and updated with a new version. However, dependent services will be down until the version is up. The old version should be kept alive until a new version is available to serve. | ✌ The single monolithic instance will be upgraded independently as the other dependent modules are shipped within monolithic. Single business operations will go down at a time. It does not affect other dependent modules in monolithic instances. All the instance is running with own dependent modules and handles complete business operation execution. The old version should be kept alive until a new version is available to serve. | |
Startup time should be minimal. | The application loads all the modules as a part of the startup process. | ✌ The startup is very fast. | The application can be configured to load specific modules only at startup which is required by monolithic instance to service operations. | |
Others | ||||
Error Tracing | Not required. | Required Error tracing between REST API calls or event tracing. | ✌ Not required. | |
Monitoring | Required | Required | Required | |
Testing | The single monolithic instance can be tested to check all the modules. | It is more complex. We need to start each microservices. | ✌ The single monolithic instance can be tested to check all the modules. | |
Service Discovery | Not required. | Required. | ✌ Not required. | |
Scaling | Multiple monolithic instances can be created. | Replicas of microservice can be created which adds more capability to handle operations supported by the specific microservice. If any operations need multiple microservice interactions, it may require to have replicas of all involved services in a single operation. Ex. Multiple replicas of order service, increase order operations to be smooth, but not other operations like credit card limit check. Let say order execution needs credit card limit check service every time, multiple replicas of both services are needed. |
✌ Replicas of monolithic instance can be created which will add more capability to handle operations supported by the specific business operation. If any operations need multiple module interactions, it does not require to have replicas of all involved modules in a single operation. Ex. Multiple replicas of order service, increase order operations to be smooth, but not other operations like credit card limit check. Let say order execution needs credit card limit check every time, multiple replicas of order service are needed and not the credit card as credit card module interaction is executed within order service monolithic instance. |
Opinions expressed by DZone contributors are their own.
Comments