Getting the Most From Your Microservices Architecture
Creating an application with a microservices architecture rather than a single structure is becoming more popular, but developing one can take time, and there are a number of factors to consider when implementing one.
Explaining Microservices Architecture
Microservices architecture is a way of developing a software system with small, modular services which interact with each other and independently to create a whole. Microservices is a popular alternative to the typical monolithic architecture, which consists of one overarching structure responsible for everything.
Why Microservices Architecture?
There are a number of reasons why microservices architecture is gaining traction over its monolithic predecessor:
- Multi-platform Support. With individual “services” responsible for different platforms and devices, each setup can be tailored to a wide range of interfaces, including laptops, tablets, phones, wearables, and the Internet of Things.
- Scalability. Rather than scaling the entire application, a microservices architecture can be scaled only at the relevant aspects.
- Bugs and Upgrades. If one component needs upgrading or there is a bug in it to be fixed, this can be done in isolation without compromising the integrity of the rest of the architecture.
Users of Microservices Architecture
Some of the biggest web-based companies have already updated their monolithic architecture into microservices. Amazon, eBay, Netflix, Twitter, Soundcloud, and even the UK Government Digital Service have implemented microservices. With billions of calls between them from a variety of applications, a microservice system can more effectively handle the number of exchanges it’s required to manage.
How to Implement Best Practices in Microservices Architecture
It can feel like a massive overhaul to dismantle one autonomous structure to create a more responsive microservices architecture. We’ve collected the best design practices to successfully implement an effective microservices-styled architecture (MSA).
#1: Domain-Driven Design (DDD). The microservices should be designed around the business’ domain. Domain modelling is perfect for identifying distinct implementations and separating them into individual aspects.
If you do not already have a domain model to work from, then mapping one from scratch is the best way to go: Create a plan of the responsibilities and capabilities of each application in order to develop a deconstructed design for the network.
#2: Domain-Driven Designed APIs. The APIs should be similarly designed in consideration with the business domain, although implementation details should be not be part of the API design.
#3: Dedicated Team per Microservice, Including DevOps Rather than having one massive team that is responsible for a giant autonomous structure, each microservice should have its own dedicated team, consisting of a product manager and DevOps (development, quality assurance, and operations) staff specifically concerned with their own application.
#4: A DevOps approach is particularly useful for implementing microservices, as developments per application can be integrated and tested without affecting the stability of the overall network and with a much shorter downtime before the update is deployed.
#5: Separate Data Storage. Each microservice should store its own cache of data, and any exchange should only occur through APIs. If the microservices are exchanging freely, with multiple applications drawing from one database, this will inevitably cause coupling between the services. Command Query Responsibility Segregation (CQRS) is a pattern that is particularly useful for providing, updating, and reading information from different models.
#6: Separate Services for Cross-Cutting Concerns, such as authentication and authorization, should be kept separate.
#7: Failure Isolation. One of the greatest benefits of a microservices-based architecture is that a fault in one microservice is unlikely to infiltrate the entire network. However, it’s important not to neglect failure isolation within the individual microservice. Techniques to be considered include:
- Self-contained services (to further contain any failures from impacting the rest of the service)
- Event-driven architecture (the software reacting to a negative event within the framework)
- Circuit-breaker design pattern (preventing the application from re-trying the same command that caused a failure until it is safe to do so)
- Timeouts (a fallback mechanism to prevent a request from waiting indefinitely for a response, such as retrying or creating an exception rule)
- Loose coupling (components are easily replaced in a failure as they do not rely on each other and are not constrained to particular principles)
- Asynchronous communication (so that the server does not need to rely on an immediate response)
- Stateless design (limiting the publicly available information about the application’s mode and actions)
This is certainly not an exhaustive list, but they are important considerations when making the shift towards a microservices structure.