Microservices have been on the tip of every software developer’s tongue for quite some time now. With the success of Netflix and their adoption of microservice architecture, the development space has moved towards supporting tools and frameworks that lend themselves to microservice development.
Microsoft has been no exception. With Web App for Containers, Azure Kubernetes Service (AKS), Bridge to Kubernetes, and the recently announced Dapr, a distributed application runtime for building microservices, Azure has become an ideal ground for developing solutions architected with microservices.
The question that remains for many would-be microservices developers is this: why should I adopt microservices? Microservices introduce more complexity in comparison to the more traditional applications and it can be a bit of a learning curve as well to decouple oneself from tried-and-true application architecture so you may need to seek some help from experienced infrastructure consultants. However, the loosely coupled nature of microservices offers several for the developer, which we explore and detail here.
What is a Microservice?
A microservice is an individual service within a larger system that is specialized for a specific function, self-contained, and loosely coupled with the other services around it. This means that each microservice is developed independently; one service can be changed and updated as needed without directly affecting the other services. The microservices treat each other as micro applications; instead of instantiated classes calling each other through methods and code, they communicate over protocols such as HTTP, just like other applications would. The orchestration of this communication presents one of the challenges of adopting microservices, but there are tools and frameworks available to help scaffold and facilitate this inter-service communication.
This visual represents a solution architecture that utilizes microservices in AKS in both DevTest and Production environments.
What are the Advantages of Microservices?
Independently Deployable and Scalable
One of the main advantages of adopting a microservice architecture is the independence of the state of deployment of each service. Each service contains its own deployment profile and scalability rules. When a service needs to be updated, it can be updated in isolation and re-deployed without affecting other services in the application.
The ability to scale services independently is another advantage that comes from the decoupled nature of things. If one microservice in the system is receiving large loads due to many other services utilizing it, then it can scale up its nodes on its own, load-balancing traffic between replicas of the service internally. Instead of having to replicate an entire monolithic application to achieve scaling and load balancing, only the services that need to scale will do so. This flexibility adds a lot of resiliency to a microservice solution.
Better Service Recovery and Fault Tolerance
The independence of services also means that when nodes or even entire services fail, the failure can be isolated to a single service. While the service is recovering, the other services can handle the downtime gracefully, continuing to function and maintain uptime until the service in question is back up and running. This means that a bug in one service or a runtime error in another doesn’t bring down the entire system and microservices can be developed to handle the temporary unavailability of dependent services.
Separation of Concerns in Development
Splitting an application into microservices means identifying separate concerns or functionality of the application and drawing clear boundaries around the responsibilities of the services. A smaller, more targeted set of functional responsibilities simplifies the codebase as well as streamlines things for the developers themselves. Smaller codebases mean smaller data models, fewer potential points of failure, and cleaner code in general. While it requires the ability to switch contexts between microservices when developing, it facilitates easier maintenance of the code. If the application grows, instead of adding more and more coupled code to a monolith, more microservices can be added, keeping the relative size of the codebases in all the microservices the same.
Flexibility in Approach
Microservices implement their own data stores or backends in best practice architecture. Single responsibility means the responsibility of the required data as well. What this also means is that unlike a traditional architecture, in which one data store is generally used, each microservice has the option to implement its data store as necessary. If a traditional relational database such as SQL is the best fit, then that can be implemented. However, in the growing landscape of NoSQL, other options fit different use cases. Document stores (think MongoDB) or graphs (Neo4j) are rapidly maturing and may fit a microservice’s specific needs. A microservice may not require a persistent data store and can operate entirely serverless. It is a flexibility that better enables microservices to be developed to meet the specific needs of the solution.
There is complexity in adopting microservices and not every use case is suitable for microservice architecture, but the shift towards distributed services and the growing landscape of tools and frameworks available to ease the adoption of these services make implementing microservices more attractive every day. The web is shifting towards these smaller, targeted services, and understanding their advantages and how to properly implement them will be a powerful asset to software developers in the years to come.