TOP 20 Microservices Design Patterns

Introduction

Microservices  is an architectural style that structures an application as a collection of loosely coupled services, which implement business capabilities.Applications built as a set of modular components are easier to understand, easier to test, and most importantly easier to maintain over the life of the application. It enables organizations to achieve much higher agility and be able to vastly improve the time it takes to get working improvements to production. The microservice architecture enables the continuous delivery/deployment of large, complex applications. It also enables an organization to evolve its technology stack.

Micro Services
Image – Micro Services /Source – MartinFowler.com

Each component is continuously developed and separately maintained, and the application is then simply the sum of its constituent components. This is in contrast to a traditional, “monolithic” application which is all developed all in one piece.

In order to actually run an application based on microservices, you need to be able monitor, manage, and scale the different constituent parts. There are a number of different tools that might allow you to accomplish this. For containers, open source tools like Kubernetes will probably be a part of your solution.

Benefits

  • Developer independence: Small teams can work in parallel and iterate faster than large teams.
  • Isolation and resilience: If a component dies, you spin up another while and the rest of the application continues to function.
  • Scalability: Smaller components take up fewer resources and can be scaled to meet increasing demand of that component only.
  • Lifecycle automation: Individual components are easier to fit into continuous delivery pipelines and complex deployment scenarios not possible with monoliths.
  • Relationship to the business: Microservice architectures are split along business domain boundaries, increasing independence and understanding across the organization.

With this context,now let us look some of the key micoservices design patterns.

Decomposition Patterns

#1.Decomposition by Business Capability

Define services corresponding to business capabilities. A business capability is a concept from business architecture modeling. It is something that a business does in order to generate value. A business capability often corresponds to a business object, e.g.

  • Payer Management is responsible for Payer
  • Customer Management is responsible for customers

Business capabilities are often organized into a multi-level hierarchy. For example, an enterprise application might have top-level categories such as Product/Service development, Product/Service delivery, Demand generation, etc.

#2.Decompose by subdomain

Define services corresponding to Domain-Driven Design (DDD) subdomains. DDD refers to the application’s problem space – the business – as the domain. A domain is consists of multiple subdomains. Each subdomain corresponds to a different part of the business., e.g.The subdomains of an online store include:

  • Product catalog
  • Inventory management
  • Order management
  • Delivery management

Deployment Patterns

#3.Multiple service instances per host

Each service is deployed as a set of service instances for throughput and availability.This pattern is about running multiple instances of different services on a host (Physical or Virtual machine).

There are various ways of deploying a service instance on a shared host including:

  • Deploy each service instance as a JVM process. For example, a Tomcat or Jetty instances per service instance.
  • Deploy multiple service instances in the same JVM. For example, as web applications or OSGI bundles.

#4.Single Service Instance per host, Virtual Machine, or Container

This pattern deploys each service in its own environment. Typically, this environment will be a virtual machine or container, although there are times when the host may be defined at a less abstract level.

This kind of deployment provides a high degree of flexibility, with little potential for conflict over system resources.Services are either entirely isolated from those used by other clients (as is the case with single-service-per-VM deployment), or can be effectively isolated while sharing some lower-level system resources (i.e., containers with appropriate security features). Deployment overhead may be greater than in the single host/multiple services model, but in practice, this may not represent significant cost in time or resources.

#5.Serverless deployment

This pattern is about using deployment infrastructure that hides any concept of servers (i.e. reserved or preallocated resources)- physical or virtual hosts, or containers. The infrastructure takes your service’s code and runs it. You are charged for each request based on the resources consumed.

Some of the prominent serverless deployment environments:

The deployment infrastructure is a utility operated by a public cloud provider. It typically uses either containers or virtual machines to isolate the services. However, these details are hidden from you. Neither you nor anyone else in your organization is responsible for managing any low-level infrastructure such as operating systems, virtual machines, etc.

#6.Service deployment platform

This pattern uses automated infrastructure for application deployment. It provides a service abstraction, which is a named, set of highly available (e.g. load balanced) service instances.e.g.,

Cross-cutting Patterns

#7.Microservice chassis

When you start the development of an application you often spend a significant amount of time putting in place the mechanisms to handle cross-cutting concerns. Examples of cross-cutting concern include:

  • Externalized configuration – includes credentials, and network locations of external services such as databases and message brokers
  • Logging – configuring of a logging framework such as log4j or logback
  • Health checks – a url that a monitoring service can “ping” to determine the health of the application
  • Metrics – measurements that provide insight into what the application is doing and how it is performing
  • Distributed tracinginstrument services with code that assigns each external request an unique identifier that is passed between services.

This pattern advises you to build your microservices using a microservice chassis framework, which handles all of the cross-cutting concerns.

Examples of microservice chassis frameworks:

#7.Externalized configuration

An application typically uses one or more infrastructure and 3rd party services. Examples of infrastructure services include: a Service registry, a message broker and a database server. Examples of 3rd party services include: payment processing, email and messaging, etc.

This pattern advises you to externalize all application configuration including the database credentials and network location. On startup, a service reads the configuration from an external source, e.g. OS environment variables, etc.

API Patterns

#8.API Gateway pattern

If you are building an online store that uses the Microservice architecture pattern and that you are implementing the product details page. You need to develop multiple versions of the product details user interface for each of the clients below:

  • HTML5/JavaScript-based UI for desktop and mobile browsers – HTML is generated by a server-side web application
  • Native Android and iPhone clients – these clients interact with the server via REST APIs

In addition, the online store must expose product details via a REST API for use by 3rd party applications.

Implement an API gateway that is the single entry point for all clients. The API gateway handles requests in one of two ways. Some requests are simply proxied/routed to the appropriate service. It handles other requests by fanning out to multiple services.Rather than provide a one-size-fits-all style API, the API gateway can expose a different API for each client. For example, the Netflix API gateway runs client-specific adapter code that provides each client with an API that’s best suited to its requirements.

The API gateway might also implement security, e.g. verify that the client is authorized to perform the request

Service discovery Patterns

#9.Client-side service discovery

Services typically need to call one another,In a modern microservice based application runs in a virtualized or containerized environments where the number of instances of a service and their locations changes dynamically.

  • Each instance of a service exposes a remote API such as HTTP/REST, or Thrift etc. at a particular location (host and port)
  • The number of services instances and their locations changes dynamically.
  • Virtual machines and containers are usually assigned dynamic IP addresses.
  • The number of services instances might vary dynamically. For example, an EC2 Autoscaling Group adjusts the number of instances based on load.

When making a request to a service, the client obtains the location of a service instance by querying a Service Registry, which knows the locations of all service instances.

#10.Server-side service discovery

Services typically need to call one another,In a modern microservice based application runs in a virtualized or containerized environments where the number of instances of a service and their locations changes dynamically.

  • Each instance of a service exposes a remote API such as HTTP/REST, or Thrift etc. at a particular location (host and port)
  • The number of services instances and their locations changes dynamically.
  • Virtual machines and containers are usually assigned dynamic IP addresses.
  • The number of services instances might vary dynamically. For example, an EC2 Autoscaling Group adjusts the number of instances based on load.

When making a request to a service, the client makes a request via a router (a.k.a load balancer) that runs at a well known location. The router queries a service registry, which might be built into the router, and forwards the request to an available service instance.

#11.Service registry

Clients of a service use either Client-side discovery or Server-side discovery to determine the location of a service instance to which to send requests.

  • Each instance of a service exposes a remote API such as HTTP/REST, or Thrift etc. at a particular location (host and port)
  • The number of services instances and their locations changes dynamically. Virtual machines and containers are usually assigned a dynamic IP address. An EC2 Autoscaling Group, for example, adjusts the number of instances based on load.

Implement a service registry, which is a database of services, their instances and their locations. Service instances are registered with the service registry on startup and deregistered on shutdown. Client of the service and/or routers query the service registry to find the available instances of a service. A service registry might invoke a service instance’s health check API to verify that it is able to handle requests

#12.Self Registration

Service instances must be registered with the service registry on startup so that they can be discovered and unregistered on shutdown.

  • Service instances must be registered with the service registry on startup and unregistered on shutdown
  • Service instances that crash must be unregistered from the service registry
  • Service instances that are running but incapable of handling requests must be unregistered from the service registry

A service instance is responsible for registering itself with the service registry. On startup the service instance registers itself (host and IP address) with the service registry and makes itself available for discovery. The client must typically periodically renew its registration so that the registry knows it is still alive. On shutdown, the service instance unregisters itself from the service registry.

Reliability Patterns

#13.Circuit Breaker

Services sometimes collaborate when handling requests. When one service synchronously invokes another there is always the possibility that the other service is unavailable or is exhibiting such high latency it is essentially unusable. Previous resources such as threads might be consumed in the caller while waiting for the other service to respond. This might lead to resource exhaustion, which would make the calling service unable to handle other requests. The failure of one service can potentially cascade to other services throughout the application.

A service client should invoke a remote service via a proxy that functions in a similar fashion to an electrical circuit breaker. When the number of consecutive failures crosses a threshold, the circuit breaker trips, and for the duration of a timeout period all attempts to invoke the remote service will fail immediately. After the timeout expires the circuit breaker allows a limited number of test requests to pass through. If those requests succeed the circuit breaker resumes normal operation. Otherwise, if there is a failure the timeout period begins again.

Data Management Patterns

#14.Database per Service

Most services need to persist data in some kind of database.Keep each microservice’s persistent data private to that service and accessible only via its API. The following diagram shows the structure of this pattern.

The service’s database is effectively part of the implementation of that service. It cannot be accessed directly by other services.

There are a few different ways to keep a service’s persistent data private. You do not need to provision a database server for each service. For example, if you are using a relational database then the options are:

  • Private-tables-per-service – each service owns a set of tables that must only be accessed by that service
  • Schema-per-service – each service has a database schema that’s private to that service
  • Database-server-per-service – each service has it’s own database server.

#15.Command Query Responsibility Segregation (CQRS)

If you have applied Database per service pattern , it is no longer straightforward to implement queries that join data from multiple services. Split the application into two parts: the command-side and the query-side. The command-side handles create, update, and delete requests and emits events when data changes. The query-side handles queries by executing them against one or more materialized views that are kept up to date by subscribing to the stream of events emitted when data changes.

Security Patterns

#16.Access token

The application consists of numerous services. The API gateway is the single entry point for client requests. It authenticates requests, and forwards them to other services, which might in turn invoke other services.Services often need to verify that a user is authorized to perform an operation.The API Gateway authenticates the request and passes an access token (e.g. JSON Web Token) that securely identifies the requestor in each request to the services. A service can include the access token in requests it makes to other services.

Observability Patterns

#17.Log aggregation

The application consists of multiple services and service instances that are running on multiple machines. Requests often span multiple service instances.

Each service instance generates writes information about what it is doing to a log file in a standardized format. The log file contains errors, warnings, information and debug messages.Use a centralized logging service that aggregates logs from each service instance. The users can search and analyze the logs. They can configure alerts that are triggered when certain messages appear in the logs.

#18.Health Check API

Sometimes a service instance can be incapable of handling requests yet still be running. For example, it might have ran out of database connections. When this occurs, the monitoring system should generate a alert. Also, the load balancer or service registry should not route requests to the failed service instance.

A service has an health check API endpoint (e.g. HTTP /health) that returns the health of the service. The API endpoint handler performs various checks, such as

  • the status of the connections to the infrastructure services used by the service instance
  • the status of the host, e.g. disk space
  • application specific logic

A health check client – a monitoring service, service registry or load balancer – periodically invokes the endpoint to check the health of the service instance.

#19.Distributed tracing

Requests often span multiple services. Each service handles a request by performing one or more operations, e.g. database queries, publishes messages, etc.

Instrument services with code that

  • Assigns each external request a unique external request id
  • Passes the external request id to all services that are involved in handling the request
  • Includes the external request id in all log messages
  • Records information (e.g. start time, end time) about the requests and operations performed when handling a external request in a centralized service

#20.Exception tracing

The application consists of multiple services and service instances that are running on multiple machines. Errors sometimes occur when handling requests. When an error occurs, a service instance throws an exception, which contains an error message and a stack trace.

Report all exceptions to a centralized exception tracking service that aggregates and tracks exceptions and notifies developers.

Like this post? Don’t forget to share it!

References : 

Summary
Article Name
TOP 20 Microservices Design Patterns
Description
Microservices is an architectural style that structures an application as loosely coupled services here we see TOP 20 design patterns
Author
Publisher Name
upnxtblog