Microservices architecture pattern

Definition

The concept of microservices defines an approach to the architecture of IT systems that divides an application into a collection of loosely coupled services that implement business requirements.

Overview

  1. Most popular architectural approach today.
  2. Extremely effective.
  3. It is used my many of the most succesful companies in the world today - particularly the web companies.
  4. As a result, lots of organizations and teams are attempting to adopt it.
  5. In reality, they often miss both the value and the costs of microservices; And end up doing something that really isn’t microservices at all; And doing the idea of a microservice a disservice; Very often, they don’t gain the benefits that they are looking for.

Microservices are cloud-native by their nature. Frameworks such as Spring Boot and Spring Cloud help you to accelerate your cloud-native development. The main motivation of migrating to cloud-native development is the ability to implement and deliver applications faster while maintaining high quality. In many cases, microservices help us to achieve this, but sometimes the monolithic approach is not a bad choice.

Problems with microservices

This very valuable architectural idea is probably not what you think it is. It is simple, right? Microservices means small services, isn’t it? No. Not really.

The first problem is that microservices is a distributed systems architecture. And however you wrap it up, distributed systems are way more complicated than non distributed systems. There are all sorts of problems that you just automatically buy into when you start distributing computing into multiple different devices.

One of the things microservices are not are - they are not services with simply a REST api. REST is another thing. It can be implemented as a microservice or not. REST may be a useful technique in implementing microservices or not. There are many different ways of approaching these. But a RESTful api does not define a microservice.

And all services are not microservices. Services - as an organizing principle for software systems has a very long history.

  1. usage of common cloud-based environments
  2. migration from relational databases to NoSQL

Some of the programming patterns that are used in microservice-based architecture

  1. service registries
  2. the configuration server
  3. circuit breakers
  4. cloud buses
  5. OAuth2 patterns
  6. API gateways

Defining characteristics

Reference: By Dave Farley of Continuous Delivery youtube channel

The defining characteristics for microservices are:

1. they are small

  1. They are understandable.
  2. They comparmentalize a problem so that we can deal with it and understand whats going to happen.
  3. A reasonable rule of thumb to figure out how small is small, or how micro is micro is, imagine throwing away your microservice and re-implementing it. How long will that take? Can you do it in a few days or a couple of weeks? If yes, it is probably on the right kind of scale. If the idea of throwing it away and re-writing it from scratch scares you, it is probably too big.

1. they are focussed on accomplishing one single task and they do it well

  1. This is really about separation of concerns; at the level of the problem domain. The microservice accomplishes one task when viewed from the outside.
  2. Implementing that task may involve a bit more; more concerns perhaps; maybe you are thinking about storage or getting data from another service; But from the outside, the service is going to be focused on achieving one task and achieving that well.

1. they are aligned with a bounded context in the problem domain

  1. Most teams miss this idea but it is an important one.
  2. Bounded context is an idea that comes from the fantastice book “Domain-driven design” by Eric Evans. It describes modeling the problem domain as an approach to designing the software.
  3. One of the key ideas of the book is bounded context.
  4. A bounded context is a defined part of software where particular terms, definitions and rules apply in a consistent way.
  5. This is part of the problem domain where the concepts are related to one another. So it makes a cohesive unit.
  6. In the sphere of microservices, it is a very important idea because those are the boundaries that we would prefer to align our services with.
  7. This is important for several reasons.
  8. First reason: If we break a problem, say a monolithic application, into a collection of smaller technical services, that doesn’t really qualify as microservices. They are not aligned with a bounded context. And you are going to suffer by the increased couplings between those components.
  9. Bounded contexts are like natural fire-breaks in the problem domain.
  10. If we align our software with those firebreaks, it means that our system is going to be naturally less-coupled. Because the problem domain is less coupled at those points. It means that we can write cleaner interfaces to our services. And have less chatty interactions between them.
  11. We should make a significant distinction between the external protocol with which the microservice exchanges information with other parts of the system vs the internal representation of that service and the model within.
  12. We need to treat seriously the difference between the design of those APIs - those entry points into our services and our consumption of those APIs from other services.
  13. If you are not using ports and adaptors in your implementation of microservices, you are probably making a big mistake.
  14. We want always to be translating at these points.

1. they are autonomous

  1. The teams that look after these microservices can make progress - alone - without the need to interact with other services or other teams. I can implement a change in the microservice without needing to coordinate with anything or anyone else.
  2. This is the biggest value of microservices.
  3. This is the thing that allow microservices to work in organizations that scale enormously.
  4. But it is also the most commonly missed attribute of microservices.
  5. Frequently, teams claiming they are implementing microservices but building, testing and deploying with other things together. That is not microservices - that is something else.
  6. Service based design != Microservice. Service based design has been around for a very long time - it has a long history. People have been building distributed service oriented systems for more than 30 years. People used the ideas of remote procedure calls and object request brokers - where they simulate interactions with component based systems in distributed systems. They moved to building Message Oriented Architectures, Service Oriented Architectures (SOA), and then into Event Driven Architectures. They have been using patterns like CQRS, microservices and reactive systems. All of these are service oriented systems. All of these are based on the concept of little bundles of logic that somehow, more discreet from one another than the classes and functions within our implementation - and so - have more abstract interfaces between them. The ideas of service orientation are extremely useful. They are an important idea in computer science and in building bigger systems.
  7. It matters for technical and organizational reasons.

Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure - Melvin Conway, 1967

  1. The architecture - the design of our systems - is closely related to the communication topologies that we employ in the organizations that we work in. This has an impact on the kinds of architectures that it is possible for teams to build; And the architecture mirrors the organizational structure. If we decide to divide up our teams on technical boundaries, we will have UI specialists, middleware specialists, DB specialists; And we are going to build a system that looks like a front-end component on the front, some applications in the middle and a database in the backend. And the teams have to coordinate and interact.
  2. Modern software architecture tends to prefer smaller more autonomous teams. For a variety of reasons, the teams want to organize themselves into more modular, autonomous teams - and build more modular software and more autonomous components. But this is not necessarily a microservice organized system. We could choose how we are going to organize the teams around these. We could put everything into one big repo and a distributed service oriented system - communicating with REST or messaging or whatever other technique. Or we could have independently deployable units of software - autonomous components that are microservices. They are not the same thing.
  3. If you can have distributed monoliths organized as a collection of services - which could be the most preferred architectural approach for many systems - what do microservices add to that? The key thing is that they are independently deployable. Deployability is one important aspect of autonomy. If we can work on changes to our service, and deploy it without necessarily interacting or communicating with other groups of people, that means we can make progress without being constrained by those groups. It means, we are developmentally less coupled with the rest of the organization. That is what independently deployable means. If I need to worry about dependencies on other services before I can release my change into Production, my software is not really independently deployable. It is not a microservice. If you always test your service with others before release, it is not independently deployable. You don’t get to force changes that you make in your service on to consumers of your service. You can’t demand that they update in step with you. That is not part of the microservices model.
  4. If our services are microservices, we build, test and deploy them independently of other services. This is the real value of microservices. It is the step that decouples organizations both technically and culturally and allows them to grow and create software at an enormously fast rate. It is the thing that differentiates organizations like Amazon from more conventionally organized firms. And this is also the real cost. Because, if you want to be able to independently deploy these services, you have to take the ability to maintain that independence really very seriously. Microservices are an organization decoupling strategy. That is what they are for. If you don’t need to decouple your organization developmentally, they are probably not the right thing to do. Because they come with this cost.

1. they are independently deployable (independent delivery)

  1. Containerization also allows single application components to be updated in isolation, without affecting the rest of the technology stack. This ensures that security and feature updates are applied rapidly, with minimal disruption to overall operations.

1. they are loosely-coupled (scalability, flexibility)

  1. They allow teams to develop software much quickly. But to achieve this, they must be loosely coupled. We need to take the separation of external and internal representation incredibly seriously. We have to invest time and development effort in keeping that separation clean. We need to treat the external interface of our microservice like a public API - because it is. We can’t demand that other people change in step with us when we make changes to our API. We must be very, very cautious when making changes. It should be changed only with great care. When consuming an API, use the minimum data that you can to reduce coupling. Make the interfaces as clean and abstract as possible. It brings in techniques like API versioning. Or multiple versions of services in some instances. These are the techniques of microservices and this is the cost of microservices. But we get some huge advantages for those costs.
  2. Scalability and resiliency is improved by splitting each individual application functions into containers.

Reading material

  1. https://microservices.io/patterns/microservices.html
  2. https://microservices.io/index.html

Types

There can be many types based on the type of classification.

Protocols

  1. RESTful web services with JSON notation
  2. gRPC
  3. SOAP

Interaction styles

  1. one-to-one communication
    1. every incoming request is processed by exactly one service instance
  2. one-to-many communication
    1. incoming requests are processed by multiple service instances

synchronous or asynchronous

reactive microservices

From version 5, Spring also supports this type of programming. There are also libraries with Reactive support for interaction with NoSQL databases, such as MongoDB or Cassandra.

publish-subscribe

This is a one-to-many interaction type where an application publishes a message that is then consumed by all listening services. Typically, this model is realized using message brokers, such as Apache Kafka, RabbitMQ, and ActiveMQ.

How does springboot fit into the microservices discussion?

See Spring - Running an app with Springboot vs standard Spring framework

Tags

  1. Spring Cloud and Cloud native development
  2. Containerization
  3. Load balancer
  4. Service registration and discovery

TODO

Distributed configuration - How can microservices use them?


Links to this note