Let us assume that you have an enterprise application to develop. Your application needs to have support for different clients including desktop browsers and mobile applications. You might additionally have an API directed for use by 3rd party applications. Your enterprise application exchanges messages, accesses databases and handles HTTP requests. There are many functional components that must work together in order to make the enterprise system a complete unit.
A microservice architecture (MSA) is what comes to the rescue in such a situation. The term microservice architecture is used to define a way of designing software as suites that can be deployed independently.
No precise definition can completely explain what an MSA is. However, common characteristics include features such as automated deployment, business capability, and decentralised control of languages.
WHAT IS MICROSERVICE ARCHITECTURE?
The term microservice architecture (MSA) has gained momentum as a new “in” term in this information technology era. MSA is a mechanism of developing software systems by focusing on single modules with well-defined interfaces and operations, that collaborate with other modules to create a complete unit.
An individual microservice is implemented with a single purpose, is self-contained, and is independent of other instances or services. These individual microservices are what makes up the whole microservice architecture.
THE CHARACTERISTICS OF MICROSERVICE ARCHITECTURE
There is no formal definition of MSA, but all MSAs have certain common characteristics:
Products and not projects
MSA perpetrates the idea that a team should own a product over its full lifetime, rather than focusing on just the delivery of a project. The aim is not just to deliver a piece of software that is considered completed but to take regular feedback about the product even after its release. This product oriented mentality also helps to create personal relationships between service developers and their users, finally improving productivity.
Componentisation of services
Any software that is built in the MSA is broken down to multiple components. Each service is componentised to be deployed, tweaked, and redeployed independently. This independence allows the integrity of the application to remain intact. Hence, when there needs to be a change in a certain service, you can just change one or more services instead of having to retest and redeploy entire applications.
Built for business
An MSA is built and organised around business capabilities. When splitting a large application into parts, different teams are formed and separated along these lines. Hence, simple changes can be optimised with ease, as budgetary approval and approval for new features becomes efficient and faster. Also, the shared responsibility imparted on a small team to manage individual components makes it easier to keep the team boundaries clear.
Microservices receive requests, process them and generate the response. This simple routing system makes the application decoupled and as cohesive as possible. The infrastructure is chosen just to route messages via the infrastructure pipes while the smart endpoints deal with what to do with the requests. Hence, it can be said that MSAs have smart endpoints and dumb pipes.
Independent microservices in an MSA differ in terms of platforms and technologies used. Hence, the old-school centralised governance mechanisms do not work for a microservice based architecture. The data management of an MSA is also decentralised. Monolithic systems use a single logical database for all applications, but each service manages its own database in a microservice based architecture.
Microservices are built to reduce operational complexity by ensuring continuous delivery and continuous integration. An MSA makes extensive use of infrastructure automation techniques by running lots of automated tests and automating deployment to each new environment.
Resistant to failure
Microservices are designed by using services as components and are designed to tolerate the failure of these services. Since diverse services communicate with each other in a microservice based architecture, any service can fail in such a case. The failed service should, in this case, allow its neighboring services to run seamlessly and bow out from the system in a graceful manner. It is to be understood that meeting this requirement adds complexities to microservices in comparison to monolithic systems.
Microservices architecture is ideal for evolutionary systems where it is not possible to anticipate the types of services required by the system, or the types of devices that may access the application. Most systems can start as monoliths and can slowly be revamped into microservices that communicate through APIs. Microservice architecture is thus an evolutionary design, as it allows for more granular release planning, independence with other services, and easier deployment.
The following problems drive the need for an MSA:
Complexity of the development of, operation of, and management of services.
When a small fix is to be done in an interdependent application, then a long cycle of validation and testing must be carried out. In the case of monolithic applications, the whole system must be rebuilt and tested.
Over time, the modularity of a monolithic or interdependent application tends to weaken. This makes it harder to carry out a small change even in a small part of the application. MSA, however, allows individual development and deployment, thus making each service self-contained and independent.
The development, operation, and management of services in an MSA make it easier to scale the application as a whole. Scaling a monolithic application, on the other hand, requires scaling the entire application solution and its resources. Hence, the problem of development, management, operation and scaling of services is reduced dramatically with the introduction to a microservice based architecture.
The usage of a microservice based architecture reduces the functional bloat and complexity of the application. Monolithic applications often expand the scope of the components by adding new functionalities to the component itself. This complicates the component and puts additional demand and bloat on the system. Keeping services independent and self-contained reduces this bloating risk.
Response rates to changes in the marketplace
With monolithic systems, response to changes in the marketplace becomes extremely difficult. MSA, on the other hand, is meant to address the market velocity needs with ease.
• The microservices are jointly owned by the business unit and the development team
• Because of independence and self-containment, microservices can cater to the changing velocity needs of the business unit with ease, without impacting the other business units
• Microservices are based on single atomic business functions and hence tend to be smaller
• Microservices can be developed in small environments and requires lower investment to support small change
• Testing a large enterprise application is a significant investment, but testing microservices requires a shorter testing cycle
• Monolithic applications have centralised governance and data management. Hence they become dependent on a single technology. On the other hand, microservices can have their own technology stack
• Coordination and inter management of microservices is easier in comparison to monolithic applications
Continuous Integration (CI) and continuous deployment (CD)
The DevOps culture today, emphasises that development and operations should be independent of each other, and autonomous teams should own the entire life cycle of an application. The distributed nature of microservices meets these expectations with ease.
Continuous integration of software and automated deployment of integrated code is possible on a microservice based architecture and not on monolithic applications.
Distributed workload between on-premise and the cloud
Microservices architecture enables the capabilities of web-oriented architecture and offers the resilience and scalability of the cloud.
Independence of services means that services can run anywhere. Hence, the migration to the cloud becomes easier. To support customer demands, services, functions, and applications can be easily transferred to the cloud continuously.
The independence of web services allows for faster failover and self-recovery. The microservices architecture offers resilience and ultimately leads to high availability and seamless interaction with users.
WHAT ARE THE BENEFITS OF MSA?
The benefits of adopting the MSA are:
As per the definition of microservices, teams operate with complete autonomy. No superior authority gives the teams any kind of direction, and there is no need for a team to coordinate with others. This offers an advantage over monolithic systems.
Teams can choose the solution that fits their microservice approach. Teams can also use different databases, different programming languages, or database management systems that are independent of other services. Each microservice has its own runtime environment and own deployment capabilities which are independent of other units in the system.
An MSA makes systems more robust. If a microservice fails, the entire application will not crash, but the failing microservice gracefully takes itself out of the system. Troubleshooting also becomes easier as the issue can be searched easily in a small, self-contained system instead of a large monolith project.
A microservice architecture also makes it possible for software products to deliver software continuously. There is no need to update the entire product in large stages as microservice development can be updated continually as they occur. Making minor changes to the monolith applications can be expensive while making changes to a small microservice is time saving and efficient.
MSA allows you to scale services up or down efficiently, with ease and with reduced cost requirements. Adding new capabilities to an existing system just means adding new microservices instead of redoing the entire application as with monolithic systems. This improves application stability, scalability, and development speed.
The complexity associated with a system is reduced with an MSA. An owner of a particular service just needs to understand the complexity of the service and not that of the entire product. Other stakeholders also need to understand just the capabilities offered by the service, instead of the internal working mechanism. This localised complexity makes it easier to create and manage a large application.
Increased business agility
Microservices are small and simple, and failure of one microservice just affects that service and not the entire system. Enterprises can hence afford to introduce new features, include new process and algorithms and meet business needs with ease. Microservices give business the capability of faster deployment, faster fault recovery, and faster delivery of features, thus increasing business agility.
Increased developer productivity
It is possible to ease in new developers to a small microservice faster than to a monolithic system. This is because it is easier to understand a small isolated functionality than the entire system at once.
Simplified maintenance and debugging
Since the code to work on is small, maintenance and debugging become faster and simpler.
Better alignment with business users
Microservices are organised around business capabilities. Working in a microservice architecture is easier for developers to understand the functionality of the service from the business perspective. The result is that the service is better aligned with the business use case.
Smaller and agile development teams
It is easier to manage teams by the microservices they work on, rather than having a big team for an entire monolithic system. Smaller teams involve fewer people who are more focused on the task at hand.
Future proofed system
The combination of microservices makes the entire system future proofed. There is no need to commit to a certain technology stack for the long term, as building new services allows you to pick up a new technology stack. Also, since services are small, they can also be rewritten using a new technology stack with ease.
WHAT ARE THE CONS OF MICROSERVICES?
MSA is not a silver bullet, and it carries its own set of drawbacks:
Microservice architecture can be complex. It is easy to understand and manage individual microservices. However, the entire system might end up being significantly complex to understand. Many components are involved in a microservice architecture. Hence, these dependencies, in turn, make the entire application complex.
Adopting a microservice architecture requires careful planning and expertise. Breaking down all components and dependencies is often a difficult deal. There might be data challenges when starting an application from scratch. These planning complexities are even more pronounced when converting a monolith to a microservice architecture.
Calculating the proper size of microservices is difficult. Make your microservice too big, and you might end up accidentally spawning a monolith. Make them too small, and you increase the dependencies of the entire application, making it difficult to scale.
Many microservice architectures include services from third-parties. These third-party applications cannot be controlled or accessed. Third party applications can change their dependencies at any time, which might end up with you having to change your entire system structure to meet the requirements.
Tracking down dependencies in a microservice architecture is difficult. Good microservice architecture has lesser dependencies and a careful tracking mechanism for dependencies that cannot be avoided. Hence, a system must be able to survive even if one microservice fails. Embedding fault tolerance into the system makes it more complex than monolithic systems.
Having multiple microservices might reduce the security of the system by making it vulnerable to hackers and cybercriminals. Microservices allow you to use multiple operating systems and languages, thus making the individual services the targets for malicious intrusions.
WHEN TO USE A MICROSERVICE ARCHITECTURE?
Before understanding the mechanism of migrating to microservices, it is important to decide when to use a microservice architecture. At the start, making an elaborate architecture consumes a lot of development time. It might seem that starting with a monolithic system is a suitable solution. However, decomposing this monolith to a set of services becomes difficult with the tangled dependencies and complex functional decomposition. Hence, knowing the exact time to shift to microservices is crucial.
HOW TO DECOMPOSE AN APPLICATION TO SERVICES?
It is known that microservices focus on single modules instead of a whole system. How exactly does a microservice architecture do that? How do microservices work?
Conway’s law states: “Organisations which design systems…are constrained to produce designs which are copies of the communication structures of these organisations.”
To illustrate further, imagine a company with two units: Admin and Accounts. There might be some questions related to both: Would it be better to allow the people from accounts to carry out administrative activities? Alternatively, Would it be suitable for people from Admin to help accounts in delegating the salary at the end of the month?
These questions are answered by the company’s set policy that: Admin will stick to supplying the company needs, by communicating with the accounts team about the requirements.
The roles of this interconnected system are split, and this is how the Admin and Accounts system will work.
Similarly, when designing a new software application as a microservice, it is important to create different projects and a corresponding team for the projects. Each project handles its own domain and communicates with other projects to make the system a whole, working unit. This helps reduce the frictions involved between business priorities, domain knowledge, and change management.
However, it is important to ensure that different projects being created by different teams, do not turn out to be different monoliths which are just connected by a communicating bridge.
To ensure that you do not accidentally spawn monoliths, it is important to start looking out for independent services from the edge of the application graph. Start with the sections which depend on nothing and nothing depends on them. Look out for services that can be easily removed from the main application and can be abstracted away into external services.
When making the shift to a microservice architecture:
• The architecture must be stable
• The services to create must be cohesive
• Each service should be testable
• Services must be coupled loosely
• Each service should be small enough to be developed by a team of 6-10 people
• Each team must own the service, and each service must be autonomous
• Each team must be able to deploy their services with minimum collaboration with other teams
There are a number of strategies that can help to decide the decomposition mechanism.
1. Decompose services by business capability
A business capability is a concept that arises from the business architecture model. A business capability is something that a business does in order to generate value. For example:
• Customer management: manages customers
• Order management: manages orders
• Product catalog management: manages the product catalogs
• Inventory management: manages the inventory of the company
These business capabilities can have its own microservice each. To decompose by business capability, one must have a proper understanding of the business as a whole. Business capabilities can be identified in terms of the organisation structure or the high-level domain model.
2. Decompose services by domain-driven design subdomain
Domain-driven design (DDD) subdomains refer to the business as the domain. One domain consists of multiple subdomains, each of which corresponds to a different part of the business. Subdomains can be:
• Core: most valuable part of the application
• Supporting: related to the business, but not a core part
• Generic: not specific to the business and is implemented using off the shelf software
To identify the subdomains, there needs to be a proper understanding of the business, its organisational structure, and the high-level domain model.
3. Decompose services by use case or verb
Decomposition by use case means defining services that are responsible for carrying out particular actions. For example, a shipping service can be considered to be one microservice that is responsible for shipping orders.
4. Decompose services by nouns or resources
Decomposing services by nouns means creating a microservice that is responsible for all the operations on all resources of the given type. For example, an Account Service can be a microservice that is responsible for carrying out all operations related to accounts, even if it spans over different departments.
HOW TO MAINTAIN DATA CONSISTENCY?
To ensure loose coupling, each service should have its own database. A service publishes an event when its data changes and other services consume that event to update their own data.
IS THERE A FUTURE FOR MICROSERVICES ARCHITECTURE?
Many developers around the world have been using the practice of microservice architecture without ever giving it a name or labeling their practice as an MSA.
Since segmentation and communication problems are solved by microservices, MSA makes applications scalable. The benefits of microservices have been proven to be really worth it.
In conclusion, when used effectively, microservices are certainly worth it. It is hence not wrong to state that microservices architecture is the future of how software will be built in the days to come.