Book Image

Embracing Microservices Design

By : Ovais Mehboob Ahmed Khan, Nabil Siddiqui, Timothy Oleson
Book Image

Embracing Microservices Design

By: Ovais Mehboob Ahmed Khan, Nabil Siddiqui, Timothy Oleson

Overview of this book

Microservices have been widely adopted for designing distributed enterprise apps that are flexible, robust, and fine-grained into services that are independent of each other. There has been a paradigm shift where organizations are now either building new apps on microservices or transforming existing monolithic apps into microservices-based architecture. This book explores the importance of anti-patterns and the need to address flaws in them with alternative practices and patterns. You'll identify common mistakes caused by a lack of understanding when implementing microservices and cover topics such as organizational readiness to adopt microservices, domain-driven design, and resiliency and scalability of microservices. The book further demonstrates the anti-patterns involved in re-platforming brownfield apps and designing distributed data architecture. You’ll also focus on how to avoid communication and deployment pitfalls and understand cross-cutting concerns such as logging, monitoring, and security. Finally, you’ll explore testing pitfalls and establish a framework to address isolation, autonomy, and standardization. By the end of this book, you'll have understood critical mistakes to avoid while building microservices and the right practices to adopt early in the product life cycle to ensure the success of a microservices initiative.
Table of Contents (16 chapters)
1
Section 1: Overview of Microservices, Design, and Architecture Pitfalls
6
Section 2: Overview of Data Design Pitfalls, Communication, and Cross-Cutting Concerns
10
Section 3: Testing Pitfalls and Evaluating Microservices Architecture

Microservice design principles

In the quest of building microservices, you will have to make several choices that will give a different flavor to your microservice architecture and its evolution over time. Microservice design principles provide the guidelines for evaluating key decisions that can affect the design of your microservice-based architecture. In principle, microservices support loose coupling and the modularity of services. Other principles can govern the design of a microservice architecture, but their importance can vary. We will cover those principles in the following sections.

Single responsibility principle and domain-driven design

A microservice should be responsible for offering a single feature or a group of related features to deliver a business capability. The only reason why a microservice interface should change is due to changes in the business capabilities offered by the microservice. This helps systems to be designed following the real-world domains and helps us visualize systems and architectures as a translation of real-world problems. Domain-driven design is an approach that helps with domain modeling and defining microservice boundaries, which helps us achieve modularity and reduces coupling.

Encapsulation and interface segregation

Each microservice owns its data, and the only way a service can communicate with other services is through well-defined interfaces. These interfaces are carefully designed by keeping their clients in mind. Rather than overloading microservice endpoints in client applications, a popular alternative is to introduce an API gateway, which will be explained later in the chapter. This technique is useful in delegating the communication responsibility to API gateways and keeping microservices focused on delivering business capabilities.

Culture of autonomy, ownership, and shared governance

The microservice architecture allows business capabilities owned by different teams to be delivered. These teams can work independently without requiring much collaboration across teams. Each team doesn't need to be assigned a single business capability; instead, they may choose from a related set of capabilities that belong to a single domain. The microservice architecture flourishes when you allow teams to have autonomy, since they can choose what they think is right to deliver the desired business capability. This doesn't mean that teams can do anything, though, but it certainly gives them the freedom to make decisions under an umbrella of formally agreed principles. These principles are called shared governance, which provides consensus across the teams regarding how they want to address different cross-cutting concerns, or how far they want to go to try different technologies. The team that builds the microservice owns it and is responsible for operationalizing it. Such cross-cutting concerns will be covered in detail in Chapter 7, Cross-Cutting Concerns.

Independently deployable

A single microservice should be independently deployable, allowing teams to roll out changes without them affecting other microservices. As part of shared governance, teams should continue to look for technologies and practices that can help them achieve better independence. This characteristic is extremely useful for operationalizing microservices at a large scale.

Culture of automation

Automation is an important concept that promotes the idea of finding opportunities for replacing manual steps with scripted programs to achieve consistency and reduce overhead. Continuous integration, continuous deployment, automated testing, and infrastructure automation are all different forms of automation that can help you reduce the overall overhead of managing microservices.

Designing for failures

Microservices are designed to be highly available and scalable. These services do fail but they should be designed to recover fast. The idea is that the failure of one microservice should not affect other microservices, which helps avoid cascading failures and allows the service to recover as fast as possible to restore the required functionality. Designing services for failure requires having a good understanding of user behavior and expectations. The goal is to keep the system responsive in case of service unavailability, alongside reduced functionality. However, service failures are inevitable and require a pragmatic approach that enables experimentation to find system vulnerabilities. This can be achieved with controlled experimentation that creates chaos to determine how the system would behave differently in different circumstances. This approach is classified as chaos engineering.

With chaos engineering, you experiment with specific areas of the system to identify their weaknesses. Chaos engineering is a practice where you intentionally introduce failures to find undiscovered system issues. This way, you can fix them before they occur unexpectedly and affect your business and users. This exercise also helps in understanding the risks and impacts of turbulent conditions, incident response, gaps in observability, as well as the team's ability to respond to incidents. Many tools can be used to perform chaos engineering, such as litmus, Gremlin, and a few others.

Observability

Observability is a capability that you build as part of a microservice architecture to allow you to identify and reason about the internal state of your system. It also helps with monitoring, debugging, diagnosing, and troubleshooting microservices and their core components in a production environment. In a microservice architecture, you collect logs, metrics, and traces to help teams analyze service behavior. Another important aspect of observability is distributed tracing, which helps in understanding the flow of events across different microservices. In practice, metrics are more important than other forms of monitoring. Many organizations invest a sizable number of resources in metrics, ensuring that they are available in real time, and then use them as the main tool for troubleshooting production issues.

In the next section, we will uncover some core fundamentals of microservices to build teams that are independent and autonomous for bringing agility.