Microservice architecture is an approach to building systems that has emerged in the context of continuous delivery, virtualization/containerization, and DevOps. It’s an architectural design where small, autonomous programs are used together to deliver a more complex service.
Microservices borrow from an old philosophy in software development: programs should focus on doing one thing, and do it well. To that end, microservices are standalone programs that expose one piece of functionality such as e-commerce payments, search, or an interface to the inventory.
Architecturally, microservices are distributed and loosely connected. This means that changes made by one team won’t break the entire application. This approach to building software is seen in utilities popular on Linux and other Unix operating systems. Instead of attempting to build a complex program, utilities such as ls, ps, grep, awk, and sed focus on one main piece (or a very small set) of functionality. More complex operations, such as locating a particular process, is accomplished by piping the output of one utility into the input of another.
So where do microservices come from and why do we want to take this approach? Short answer: software is complex, and microservices attempts to make it easier. To understand why, you have to explore one alternative: the monolith.
Monolithic architecture is an alternative to the microservice architecture. Monolithic applications put all of the functionality together in a single program binary.
When an application is first being developed, utilizing a monolithic architecture often makes sense. It provides a way for all of the functionality to run within a single process, and enables the features to be divided up using the features of the programming language the application is written in.
But even with care and good design, it is easy for frustrations to arise. Splitting up logic gets hard, and you often can feel the pain points of one part of the application in an unrelated section.
What are Microservices?
Microservice architecture attempts to address frustrations by transforming the components of the monolith into a set of processes that can communicate with other services through a well-defined interface using a lightweight protocol (such as HTTP, AMQP, or Kafka). Microservices tend to be built around business capabilities where each service is scoped for a simple purpose. Each service frequently runs in its own process, which means that it can be scaled independently of the rest of the system or shut down for maintenance without the need to take the whole system offline.
Beyond these broad principles, there is not a formal definition a “microservice.” For this reason, it is frequently called an architectural style rather than a specific pattern or specification. Microservices also frequently (but not always) use:
- Service-based components
- Functionality grouped around business capabilities
- Smart endpoints and dump pipes
- Utilization of technologies best suited for a specific challenge
- Decentralized data management
- Fault tolerant design that is capable of dealing with service outages and component failures
This approach has proven to be beneficial, particularly for large enterprise applications which are developed by a team of developers that are locationally and culturally diverse. Some benefits include:
- Developer independence and understanding
- Improved isolation and resilience
- Lifecycle automation
- Relationship to the business
Service-based components that focus one major piece of functionality. This is different than using libraries as components, as it prevents issues where needing to change a single component results in the need to redeploy the entire application. A second major benefit provided by grouping components as services is that it becomes necessary to provide an explicit published interface that other parts of the system they use.
Organized By Business Capability
Technical teams are often split by discipline. This will often result in a database team, a UI team, a backend team, operations team, and others. Organizations that strongly follow a microservices strategy will often organize teams based on the business capabilities. Rather than a database team, there might be the e-commerce team, the content team, etc. The goal is to allow teams to own their own products from concept, through implementation, to deployment. This allows the developers to give the software the opportunity to own it through the entire product lifecycle.
Smart Endpoints and Dumb Pipes
A reticence to put application “intelligence” into protocols, but instead building that logic into endpoints of the system, an approach called “Smart endpoints and dumb pipes.” This allows applications built on top of microservices to be both decoupled and as cohesive as possible. This allows the components to work similar to the Unix tools mentioned earlier: receive a piece data, apply appropriate logic, and produce a response which can then be filtered to a separate system downstream.
Two protocols often utilized for microservices include:
- HTTP, often used to expose some type of REST interface
- lightweight messaging protocols such as the advanced message queuing protocol (AMQP) or the Apache Kafka protocol
One of the greatest challenges in building a microservice based application, is accounting for the need to communicate over the network. In a microservice, there is an overhead with every remote call and it becomes important to balance the benefits against the cost.
Decentralized Data Management
In microservices, the idea of “the right tool for the job” is often extended to how data is stored and retrieved. Services which manage state come in many different varieties. Some require a high degree of fidelity and full ACID (atomicity, consistency, isolation, and durability) compliance where all data writes should block and be acknowledged before allowing reads. Others can be more flexible and are able to work with basic availability, soft state, and eventual consistency (this alternative is sometimes referred to as BASE).