Embracing Microservices Design - Ovais Mehboob Ahmed Khan - E-Book

Embracing Microservices Design E-Book

Ovais Mehboob Ahmed Khan

0,0
27,59 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

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.

Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:

EPUB
MOBI

Seitenzahl: 370

Veröffentlichungsjahr: 2021

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Embracing Microservices Design

A practical guide to revealing anti-patterns and architectural pitfalls to avoid microservices fallacies

Ovais Mehboob Ahmed Khan

Nabil Siddiqui

Timothy Oleson

BIRMINGHAM—MUMBAI

Embracing Microservices Design

Copyright © 2021 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the authors, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

Group Product Manager: Richa Tripathi

Publishing Product Manager: Alok Dhuri

Senior Editor: Rohit Singh

Content Development Editor: Kinnari Chohan

Technical Editor: Karan Solanki

Copy Editor: Safis Editing

Project Coordinator: Deeksha Thakkar

Proofreader: Safis Editing

Indexer: Tejal Daruwale Soni

Production Designer: Jyoti Chauhan

First published: September 2021

Production reference: 2221021

Published by Packt Publishing Ltd.

Livery Place

35 Livery Street

Birmingham

B3 2PB, UK.

ISBN 978-1-80181-838-4

www.packt.com

I would like to thank my family for supporting and encouraging me in every goal of my life.

– Ovais Mehboob Ahmed Khan

I dedicate this book to my parents, wife, and children for their unwavering support and encouragement.

– Nabil Siddiqui

I would like to dedicate this book to my father, John T. Oleson. Also, I would like to thank Ovais and Nabil for inviting me to be a part of this book, and my family for their loving support.

– Timothy Oleson

Foreword

In the last 5 years, the microservice architecture design approach has established itself in the software engineering industry as the primary way to build modern, scalable, resilient services. This has been driven by the wave of cloud adoption and a major shift toward “cloud-native” service development, often built with microservice architectures (both stateless and stateful) that run on the cloud and the edge and embracing the diversity of programming languages and frameworks.

It’s not that other architectures’ design approaches, such as client/server, are bad; they just address a different need focusing on medium- to large-scale organizations for their scale and resilience. In the far more competitive services world that has emerged, where delivering new features on a regular basis is expected, and a continuous integration and delivery approach is required, the microservices architecture has become the de facto standard for building them. However, a microservice architecture alone was not enough to drive this adoption without suitable distributed systems hosting platforms to run these services on that provided the horizontal scaling, automated rollouts, load balancing, and self-healing, such as Kubernetes, Docker Swarm, and Azure Service Fabric. These infrastructure platforms and the newer serverless container platforms have been instrumental in the rise of the microservice architecture approach.

This book takes you along the journey of understanding, using, and applying microservice design principles and patterns, consolidated into a comprehensive set of guidance and supported by the authors’ real-world experiences. Chapters such as Chapter 10, Evaluating a Microservice Architecture, enable you to see the bigger picture of your goals, with the other chapters diving into the best approach and pitfalls to watch out for. Although microservices may seem daunting at first, with the need for service discovery, observability, security, and separated state deployed across machines in a distributed manner, there are tools, frameworks, and runtimes that have emerged to greatly simplify the burden on developers. These include many of the Cloud Native Computing Foundation (cncf.io) technologies, and the Distributed Application Runtime (dapr.io), covered in Chapter 3, Microservices Architecture Pitfalls, which greatly ease the burden for developers, by codifying best practices into APIs for use from any language.

I am confident that you will find this book invaluable in your microservices design journey and use it frequently to design applications for the modern services era of computing.

Mark Fussell

Microsoft Partner Program Manager

Founder of the Distributed Application Runtime (Dapr) and Azure Service Fabric

Contributors

About the authors

Ovais Mehboob Ahmed Khan is a seasoned programmer and solution architect with nearly 20 years of experience in software development, consultancy, and solution architecture. He has worked with various clients across the world and is currently working as a senior customer engineer at Microsoft. He specializes mainly in application development using .NET and OSS technologies, Microsoft Azure, and DevOps. He is a prolific writer who has written several books and articles on various technologies. He really enjoys talking about technology and has given a number of technical sessions around the world.

Nabil Siddiqui is an open source contributor and technology speaker who is currently working as a cloud solution architect at Microsoft, focusing on application innovation. He is well versed as a software engineer, consultant, trainer, and architect. He has around 20 years of experience, ranging from desktop applications to highly distributed applications on different platforms using various programming languages. During his career, he's accomplished various technical challenges and worked on a broad range of projects that have given him rich experience in designing innovative solutions to solve difficult problems.

Tim Oleson, a customer engineer at Microsoft, focuses on domain-driven design, Cosmos DB, Microsoft Azure PaaS, and Azure Kubernetes Service. He is a seasoned software engineer, consultant, trainer, and architect. He has 20+ years of experience, ranging from web applications to highly distributed service-oriented applications.

About the reviewers

Ovais Khan is a seasoned software engineer and technical leader who has architected, built, and operated a number of microservices. Ovais has extensive experience of building and operating large-scale distributed systems, cloud-scale database systems, and multi-cloud systems. He is currently working as a software engineer at Snap Inc., where he has worked on NoSQL storage solutions and live data migrations and transitioned a number of features from a monolith to microservices. Prior to that, Ovais worked at Microsoft, where he was part of the Azure Storage, Office 365, and SharePoint teams.

David McGhee is a technical program manager at Microsoft in the Commercial Software Engineering team focusing on intelligence within government in Australia. He has a sustained performance over 28 years in many distributed applications, from broadcast television to real-time financial services. David has led many teams and embraced technology firsts, including Azure in its infancy. This background has inevitably led to many failures and learnings, even successes, in cloud solution architecture. He enjoys the charm of conversation this discourse creates and opportunities for teams to get better.

Table of Contents

Preface

Section 1: Overview of Microservices, Design, and Architecture Pitfalls

Chapter 1: Setting Up Your Mindset for a Microservices Endeavor

Philosophy of microservices

Microservice design principles

Single responsibility principle and domain-driven design

Encapsulation and interface segregation

Culture of autonomy, ownership, and shared governance

Independently deployable

Culture of automation

Designing for failures

Observability

Building teams to deliver business value faster

Benefits of microservices

Agility

Maintainability

Scalability

Time to market

Technology diversity

Increased reliability

Challenges of microservices

Organizational culture

Adoption of DevOps practices

Architectural and operational complexity

Service orchestration and choreography

Observability

End-to-end testing

Double mortgage period

Platform investment

Microservice architecture components

Messages

Persistence and state management

Orchestration

Service discovery

API gateway

Reviewing leadership responsibilities

What business/technology leaders must know

What architects must know

The role of the product manager, product owner, and scrum master

Defining core priorities for a business

Using the twelve-factor app methodology

Code base

Dependencies

Config

Backing service

Build, release, and run

Processes

Port binding

Concurrency

Disposability

Dev/prod parity

Logs

Admin processes

Additional factors for modern cloud-native apps

API first

Telemetry

Security

Summary

Questions

Further reading

Chapter 2: Failing to Understand the Role of DDD

What are microservices and how do they align with DDD?

Autonomous

Independently deployable

Data ownership

Communication

Technology-agnostic

Gateway pattern service discovery

Benefits and challenges of microservices as compared to DDD

Lack of team alignment

Lack of governance

The whole is greater than the sum of its parts

Autonomy

What comes first – the data or the events?

Microservices are based on science

Complex or not complex – that is the question

Obvious contexts – "the domain of best practice"

Snowden's complicated contexts – "the domain of experts"

Snowden's complex contexts – "the domain of emergence"

A thin line between complicated and complex

Snowden's chaotic context – "the domain of novel solutions"

Snowden's disorder contexts – "the space in the middle"

Our path is clear

Event storming

DDD

A lack of awareness of stakeholder needs

A knowledge-crunching domain model

UL

Binding the model to the implementation of our services

Not a silver bullet

Boundaries are important

Bounded contexts

Context maps

Relationships between teams

Anti-corruption layer

Open host

Aggregates

Transactional boundary

Aligned teams

Iterative process

Summary

Questions

Further reading

Chapter 3: Microservices Architecture Pitfalls

Layered architecture and its challenges

Microservice architecture

Over-architecting microservices

Entity microservices

The aggregator microservice

Nanoservices

Overusing frameworks and technologies

Not abstracting common microservice tasks

Dapr – LEGO® for microservices

Lack of knowledge about the microservice platform

Embracing containers

Embracing the cloud-native approach

Embracing micro platforms

Neutralizing the benefits of microservices by adopting a frontend monolithic architecture

Micro frontends

Summary

Questions

Further reading

Chapter 4: Keeping the Replatforming Brownfield Applications Trivial

Not knowing the fundamentals when replatforming brownfield applications

Why we should go for a microservice architecture

Factors to consider when replatforming monolithic to a microservices architecture

The decoupling approach

Overlooking availability, reliability, and scalability when designing a microservices architecture

Availability

Reliability

Scalability

Sharing dependencies using older techniques

Building self-contained services

Reinventing is not an anti-pattern in microservices

Summary

Questions

Further reading

Section 2: Overview of Data Design Pitfalls, Communication, and Cross-Cutting Concerns

Chapter 5: Data Design Pitfalls

The pitfalls of keeping a single shared database

Embracing polyglot persistence

Normalizing read models

Denormalizing read operations or keeping flat tables

Understanding the CQRS principle

Types of CQRS

CQRS and microservices

The problem we are trying to solve with CQRS

The solution

Challenges when implementing the CQRS pattern in our microservices

The pitfalls of not knowing how to handle transactions

Not choosing the right consistency and concurrency

The choreography implementation of a saga

The orchestration implementation of a saga

Knowing how to perform reporting

The API composition pattern

Summary

Questions

Chapter 6: Communication Pitfalls and Prevention

The fundamentals of microservices communication

Synchronous versus asynchronous communication

Messages and message types

Asynchronous message-based communication

Different architectures and their communication styles

Direct client-to-microservice communication

The API gateway pattern

The overly complicated API gateway

Multiple gateways – backends for the frontends

Materialized view patterns

Request timeout

Retry patterns

Circuit breaker patterns

Long chains of synchronous calls – the retry storm

Scalable infrastructure

Load balancing, throttling, and request classifications

Exponential backoff, jittering, and circuit breakers

Only allowing the immediate layer to retry

The dark side of event-driven microservices

Event design pitfalls

Avoiding service versioning

Semantic versioning

HTTP/REST API versioning approaches

gRPC service versioning

Event versioning

Service meshes

Dapr versus service meshes

Summary

Questions

Further reading

Chapter 7: Cross-Cutting Concerns

Microservices chassis patterns

Microservices application needs

Cross-cutting pitfalls

Embedding security handling inside microservices

Not considering resiliency when building microservices

Not considering idempotency when building microservices

Embedding protocol translation inside microservices

Message transformation coupling with microservices

Directly exposing microservices to consumers

Keeping configuration inside microservices

Undiscoverable microservices

Not maintaining a service template or framework

Not paying attention to logging and monitoring

Summary

Questions

Section 3: Testing Pitfalls and Evaluating Microservices Architecture

Chapter 8: Deployment Pitfalls

Failing to establish a deployment strategy

Rolling deployment

Canary deployment strategy

A/B testing deployment strategy

Blue/green deployment strategy

Traffic shadowing deployment strategy

Deploying Pods in Kubernetes

Using outdated tools and technologies

Failing to obtain cooperation from all teams

Not considering Infrastructure as Code (IaC) for environment setup

Not knowing the core principles of DevOps

Feature management

Agile practices

Rollback strategy

Using gates and approvals in Azure DevOps

Deployment stamps pattern

Deployment rings

Geode pattern

Summary

Questions

Chapter 9: Skipping Testing

The shift-left testing strategy

The testing pyramid

Unit testing

The unit testing life cycle

Types of unit testing

Scope of units

Strategy

Tools

Frameworks and test maintenance

End-to-end testing

The two types of end-to-end testing

White box and black box environments

Journey testing

Tools

Integration testing

Strategy

Contract testing

Tools

Load testing

Strategy

Tools

Summary

Questions

Further reading

Chapter 10: Evaluating Microservices Architecture

Identifying the core priorities of a business

Managing architectural decisions

Team structure

Choosing the right methodology

Decomposition strategy

Evaluating the DevOps capability

Understanding which part of the business is going to change more rapidly

Infrastructure readiness

Release cycles

Communication protocol across services

Exposing services to clients

Distributed transaction handling

Service development

Capabilities of the hosting platform

Deployment strategy

Monitoring services

Assigning a correlation token to each service request

Defining a microservices chassis framework

Shift-left approach for testing and security

Summary

Assessments

Chapter 1: Setting Up Your Mindset for Microservices Endeavor

Chapter 2: Failing to Understand the Role of DDD

Chapter 3: Microservices Architecture Pitfalls

Chapter 4: Keeping the Re-Platforming of Brownfield Applications Trivial

Chapter 5: Data Design Pitfalls

Chapter 6: Communication Pitfalls and Prevention

Chapter 7: Cross-Cutting Concerns

Chapter 8: Deployment Pitfalls

Chapter 9: Skipping Testing

Other Books You May Enjoy

Preface

Embracing Microservices Design targets architects and developers who want to design and build microservices-based applications following the right principles, practices, and patterns and avoiding the fallacies and anti-patterns that may lead to bad implementation. The adoption of microservices is growing due to various benefits, such as agility, maintainability, technology diversity, scalability, innovation, faster time to market, and increased reliability. However, it comes with many challenges, such as a change in the organization's culture, a learning curve, understanding and modeling business domains, architecture and operational complexity, observability, and end-to-end testing.

This book is divided into three sections. The first section is focused on a microservices introduction and looking at design and architecture pitfalls followed by an alternative approach to avoid those pitfalls. The second section is focused on data design pitfalls, communication challenges and preventions, and cross-cutting concerns. The last section is focused on deployment pitfalls and best practices when setting up the deployment strategy, the need for testing, challenges, and how to evaluate the potential application when transforming from a monolithic architecture to a microservices architecture.

Who this book is for

This book is for architects and developers who are involved in designing microservices and related architectures. Working proficiency with microservices is assumed to get the most out of this book.

What this book covers

Chapter 1, Setting Up Your Mindset for Microservices Endeavor, teaches you about the role of different individuals while initiating a microservices endeavor, understanding the importance of building teams, and investing in your learning to execute the microservices adoption strategy according to the defined charter. This chapter also discusses the guidelines for building scalable, maintainable, and portable applications while adopting the 12-Factor App methodology.

Chapter 2, Failing to Understand the Role of DDD, teaches you about the importance of understanding domain-driven design to build cohesive services with bounded context. This chapter will re-examine the characteristics and properties of microservices with respect to domain-driven design and how it relates to building microservices. You will also learn about the importance of team building, governance, and the awareness of stakeholders.

Chapter 3, Microservices Architecture Pitfalls, teaches you about various architecture pitfalls while building microservices. It covers the complexities and benefits of microservices by relating them to various architecture practices and how they can be improved by using different patterns. Furthermore, it discusses the importance of understanding the pros and cons of various frameworks and technologies. Finally, it emphasizes the benefits of abstracting common microservices tasks and the drawback of a monolithic frontend.

Chapter 4, Keeping the Replatforming of Brownfield Applications Trivial, teaches you the techniques of replatforming brownfield applications followed by some patterns that can be used. Transitioning from a monolithic to a microservices architecture is not a straightforward process and there are many factors to consider, such as availability, reliability, and scalability, which are also discussed later in this chapter. Finally, it discusses some of the drawbacks of reusing monolithic application components rather than rewriting them to take advantage of emerging technologies that may offer better alternatives.

Chapter 5, Data Design Pitfalls, teaches you the importance of decomposing the database of a monolithic application into a set of microservices where each microservice manages its own database. Normalizing data in microservices could be an anti-pattern in many scenarios and this chapter discusses the reasons this should be avoided. This chapter covers strategies to break data out of monolithic databases and examines the pitfalls of not knowing how to handle transactions. You will also learn about atomic transactions across a distributed architecture using sagas. Finally, this chapter covers the pitfalls of not knowing how to perform reporting by implementing an API that is responsible for building complex reports for business analysis.

Chapter 6, Communication Pitfalls and Prevention, teaches you about various communication styles for microservices architecture, their challenges, and potential solutions. You will also learn about different techniques to enable resilient inter-process communication between microservices. Furthermore, it discusses the challenges of event-driven architecture and how they can be addressed using different approaches. Finally, you will learn about service meshes and how they compare to Dapr.

Chapter 7, Cross-Cutting Concerns, teaches you about the importance of the microservices chassis pattern and its use cases. This chapter starts with discussing some common needs for every microservices-based application and the pitfalls when addressing these concerns.

Chapter 8, Deployment Pitfalls, teaches you about various deployment pitfalls by starting with the necessity of having different deployment techniques. This chapter discusses the importance of using the right and dated tools and technologies to avoid failures. After that, you will learn about DevOps practices and factors to be considered, such as feature management, agile practices, a rollback strategy, approvals, and gates, when implementing it. Finally, this chapter covers various deployment patterns, such as deployment stamps, deployment rings, and geodes, and where they can be applied.

Chapter 9, Skipping Testing, teaches you about the importance of testing to the development and deployment of microservices. Skipping testing is not a good practice and can lead to failure. However, this can be avoided by shifting your testing to the left of your development life cycle. This chapter covers some strategies related to shift-left testing and the types of testing that support this approach.

Chapter 10, Evaluating Microservices Architecture, teaches you about some essential factors to consider while evaluating a microservices architecture. Giving these factors high priority while developing or replatforming an app will help you identify areas where improvement needs to happen.

Download the color images

We also provide a PDF file that has color images of the screenshots and diagrams used in this book. You can download it here: https://static.packt-cdn.com/downloads/9781801818384_ColorImages.pdf.

Conventions used

There are a number of text conventions used throughout this book.

Code in text: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "The invoice generation can subscribe to payment_recieved and perform the necessary action to generate the invoice. Once the invoice is generated, the system will generate an invoice_generated event, which can be processed by the notification system to send notifications."

Bold: Indicates a new term, an important word, or words that you see onscreen. For instance, words in menus or dialog boxes appear in bold. Here is an example: "Trusted Host is the system or platform used to host the microservices."

Tips or important notes

Appear like this.

Get in touch

Feedback from our readers is always welcome.

General feedback: If you have questions about any aspect of this book, email us at [email protected] and mention the book title in the subject of your message.

Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/support/errata and fill in the form.

Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.

If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.

Share Your Thoughts

Once you've read Embracing Microservices Design, we'd love to hear your thoughts! Please click here to go straight to the Amazon review page for this book and share your feedback.

Your review is important to us and the tech community and will help us make sure we're delivering excellent quality content.

Section 1: Overview of Microservices, Design, and Architecture Pitfalls

In this section, you'll learn about the fundamentals of microservices, the importance of domain-driven design, architecture pitfalls, and the decomposition strategy. This section comprises the following chapters:

Chapter 1, Setting Up Your Mindset for Microservices EndeavorChapter 2, Failing to Understand the Role of DDDChapter 3, Microservices Architecture PitfallsChapter 4, Keeping the Replatforming of Brownfield Applications Trivial

Chapter 1: Setting Up Your Mindset for a Microservices Endeavor

Microservices is an architectural style that structures an application into multiple services that encapsulate business capabilities. These microservices are usually much smaller, both in terms of scope and functionality, compared to traditional services. They have logical and physical separation, and they communicate with each other via messages over a network to form an application.

Adopting the microservice architecture is a journey that requires a mindset that can embrace changes in culture, processes, and practices. In essence, organizations need to go through several changes to increase agility and adaptability to achieve their goals and deliver business value.

In this chapter, we will help you understand the philosophy of microservices and the various aspects that help organizations with their digital transformation. We will also learn about microservice design principles and their components, along with their benefits and challenges. Finally, we will discuss the role of leadership and how to get started by adopting widely accepted practices in the industry.

The following topics will be covered in this chapter:

Philosophy of microservicesMicroservice design principlesBuilding teams to deliver business value fasterBenefits of microservicesChallenges of microservicesMicroservice architecture componentsReviewing leadership responsibilitiesDefining core priorities for a businessUsing the twelve-factor app methodologyAdditional factors for modern cloud-native apps

This chapter aims to help you understand the key concepts of microservices and their potential for bringing change that can fuel business growth for organizations. In addition, we will discuss the role of leadership in shifting the mindset by building effective teams that embrace change to deliver business value faster. Finally, we will dive into the "Twelve-Factor App" methodology, which has helped many organizations in their successful adoption of microservices.

Philosophy of microservices

The digital revolution is disrupting every industry to fulfill the unmet demands of its users and embrace digital transformation to transform their current businesses. Digital transformation allows businesses to adapt quickly to the changing business conditions and create value for their end users. Digital transformation is about empowering your employees, engaging your customers, transforming products, and optimizing operations. The essence of digital transformation is in a growth mindset, where organizations invest in improving their internal capabilities, processes, and systems to bring change that drives business and societal outcomes. Many of these systems are due for a change that would enable them to innovate at a rapid pace and reimagine the future to deliver exciting experiences. In the last few decades, most of these systems were built using a monolithic architecture, which is relatively difficult to change and maintain as it grows and becomes complex. Though the Service-oriented architecture (SOA) was a major improvement over the monolithic architecture, it has its own challenges, such as when the application grows, it becomes a distributed monolithic application, which is again difficult to maintain or extend. The focus of SOA is more on reusability and integration, where services constantly exchange messages in return for tasks to be executed. The messaging platform is the backbone of SOA and is responsible for service discovery, orchestration, routing, message transformation, message enrichment, security, and transaction management. The major downside of SOA is that the information is shared and knowledge of the business domain is scattered across the Enterprise Service Bus (ESB), which makes it difficult to change the service.

Microservices is an evolution of the architecture style that addresses the pain points of other architecture styles to enable rapid change and scale. Microservices also enable continuous delivery of business capabilities. The effort of concentrating on and segregating business capabilities from each other in individual services enables organizations to build systems that are modular, isolated, and loosely coupled in nature. These characteristics play a crucial role in helping organizations build dedicated teams that are focused on delivering engineering velocity. Teams are isolated to develop and deploy microservices independently, without any major collaboration required. However, if there are dependencies between services and the services haven't been modeled properly, they undergo extensive collaboration, violating the isolation as a benefit. The microservice architecture also enables organizations to build services with autonomy that embraces change and lowers the risk of failures because of service independence.

Microservices have changed the application development paradigm, where new fundamentals have surfaced and are successful at building and operationalizing microservices. Organizations need to start with the right mindset and build a culture of ownership across small teams to continuously deliver value to their end users.

Now that you have a basic understanding of the philosophy behind microservices, next, we will go through microservice design principles.

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.

Building teams to deliver business value faster

The microservice architecture encourages the idea of building small, focused, and cross-functional teams to deliver business capabilities. This requires a shift in mindset, led by team restructuring. In 1967, Melvin E. Conway introduced the idea:

"Any organization that designs a system will inevitably produce a design whose structure is a copy of the organization's communication structure."

- Conway's Law

Therefore, if an organization needs to build software systems that are loosely coupled, then they need to make sure that they build teams that have a minimum dependency to allow them to function with autonomy.

A team is defined as a cohesive and long-lived group of individuals working together on the same set of business problems, owning a problem space/business area, and having sufficient capacity to build and operate. In essence, the team needs to fully understand the piece of software they are building and operating. This helps them build confidence in the software, optimize lead time, and deploy more frequently to bring agility. In practice, the team's size varies, depending on the size and complexity of the service. Adding a new member to a team adds new connections, resulting in communication overhead, which affects productivity. Organizing teams based on features and components is considered a standard approach to building teams to facilitate collaboration and bring cross-functional skills together. Recently, Matthew Skelton and Manuel Pais introduced a structure that lowers the cognitive load of agile teams by presenting fundamental team topologies in their book Team Topologies. There are four fundamental team topologies, as discussed here:

Stream-aligned team: The stream-aligned team is a cross-functional team that's aligned to the value stream of the business and is responsible for delivering customer value with minimal dependencies. They know their customers and apply design thinking to understand business requirements to address customer needs. They support their service in production and are focused on continuous improvement and quality of service. The stream-aligned team is long-lived and has complete ownership of the service. They are responsible for building, operating, diagnosing, and supporting these services during their life cycles.Enabling team: The role of the enabling team is to provide support and guidance to stream-aligned teams in adopting tools, technologies, and practices that can help them perform better. Enabling teams are formed to identify areas of improvement and promote the learning mindset by keeping the wider organization aware of new technologies and best practices. Depending on their purpose, enabling teams can be short-lived or long-lived in an organization. However, their engagement with stream-aligned teams is only for a short period. Once the required capability is achieved, the enabling teams move to support other teams.Complicated subsystem team: The complicated subsystem teams are formed to address the requirements of complex subsystems, which can add significant cognitive load to stream-aligned teams and affect their ability to stay focused on the business domain. They are responsible for developing and operationalizing these systems to ensure their service availability when it comes to consuming other value streams.Platform team: The platform team is responsible for providing infrastructure support to enable stream-aligned teams to deliver a continuous stream of value. They ensure that the capabilities offered by the platform are compelling and provide a good developer and operator experience for consuming and diagnosing these platform services. These services should be accessible via APIs, thus enabling self-service and automation. The platform team is aligned to the product life cycle and guarantees that the stream-aligned teams are getting the right support on time to perform their duties. These services are usually bigger and supported by larger teams.

When you adopt a microservice with DevOps, individuals are responsible for handling both the development and operations of a microservice. These microservices are built with the guidance provided by product managers and product owners. In the real world, teams start small until they grow big and add complexity, before being subdivided into multiple teams to ensure autonomy and independence. For example, your application may need to build multiple channels to interact with its customers and want to work with teams with capabilities around iOS and Android, or they may have to add a notification functionality that needs a separate team altogether. In these teams, individuals have a shared responsibility, where design decisions are usually led by senior engineers and discussed with the team before implementation.

Now, let's learn about the advantages that microservices bring.

Benefits of microservices

One of the key benefits of microservices is the "shift of complexity." We managed to shift the complexity of monolithic applications to multiple microservices and further reduce the individual complexity of the microservice with bounded contexts, but we also increased more complexity to operationalize it. This shift in complexity is not bad, as it allows us to evolve and standardize automation practices to manage our distributed systems well. The other benefits of microservices will be discussed next.

Agility

The microservice architecture promotes experimentation, which allows teams to deliver value faster and help organizations create a competitive edge. Teams iterate over a small piece of functionality to see how it affects the business outcome. Teams can then decide if they want to continue with the changes or whether they should discard the idea to try new ones. Teams can develop, deploy, maintain, and retire microservices independently, which helps them become more productive and agile. Microservices give teams the autonomy of trying out new things in isolation.

Maintainability

The microservice architecture promotes building independent, fine-grained, and self-contained services. This helps developers build simple and more maintainable services that are easy to understand and maintain throughout their life cycle. Every microservice has its own data and code base. This helps in minimizing dependencies and increasing maintainability.

Scalability

The microservice architecture allows teams to independently scale microservices based on demand and forecast, without affecting performance and adding significant cost compared to monolithic applications. The microservice architecture also offers a greater deal of parallelism to help with consistent throughput to address increasing load.

Time to market

The microservice architecture is pluggable, so it supports being able to replace microservices and their components. This helps teams focus on building new microservices to add or replace business capabilities. Teams no longer wait for changes from different teams to be incorporated before releasing new business capabilities. Most of the cross-cutting concerns are handled separately, which helps teams in achieving faster time to market. These cross-cutting concerns will be covered in detail in Chapter 7, Cross-Cutting Concerns.

Technology diversity

The microservice architecture allows teams to select the right tools and technologies to build microservices rather than locking themselves in with decisions they've made in the past. Technology diversity also helps teams with experimentation and innovation.

Increased reliability

The microservice architecture is distributed in nature, where individual microservices can be deployed multiple times across the infrastructure to build redundancy. There are two important characteristics of the microservice architecture that contribute to the increased reliability of the overall system:

Isolating failures by running each microservice in its own boundariesTolerating failures by designing microservices to gracefully address the failures of other microservices

So far, we've learned about the benefits of microservices. However, implementing microservices does bring a few challenges that need to be considered. We will look at these in the next section.

Challenges of microservices

In this section, we will discuss the different challenges you may face as you embark on your microservices journey.

Organizational culture

One of the major hurdles in moving to microservices is the organizational culture, where teams were initially built around technical capabilities rather than delivering business capabilities. This requires an evolving organization, restructuring teams, and changing legacy practices.

Adoption of DevOps practices

DevOps provides a set of practices that combines development and operations teams to deliver value. The basic theme is to shorten the development life cycle and provide continuous delivery with high software quality. Adopting DevOps practices is important for any organization to bring changes faster to market, increase deployment frequency, lower the change failure rate, bring a faster mean time to recover, and a faster lead time for change that delivers value to end users. There are various products that support implementing DevOps practices. Azure DevOps is one of the most popular tools that provides an end-to-end DevOps toolchain. Also, ensure that the necessary changes are made to change management processes, including change control and approval processes so that they align with DevOps practices.

Architectural and operational complexity

The microservice architecture is distributed in nature, which presents several challenges compared to a monolithic architecture. There are more moving parts, and more expertise is required for teams to manage them. A few of those challenges are as follows:

Unreliable communication across service boundaries: Microservices are heavily dependent on the underlying network. Therefore, the network infrastructure has to be designed properly and governed to address the needs of communication, as well as to protect the infrastructure from unwelcome events.Network congestion and latency: Network congestion is a temporary state of a network that doesn't have enough bandwidth to allow traffic flows. Due to this network congestion, different workloads may experience delayed responses or partial failure, resulting in high latency.Data integrity: In a microservice architecture, a single business transaction may span multiple microservices. Due to any transient or network failure, if any service fails, it may affect some part of the transaction that creates data inconsistencies across different microservices, resulting in data integrity issues.

Service orchestration and choreography

There is no single way of specifying how different services communicate with each other and how the overall system works. Orchestration introduces a single point of failure by controlling the interaction of different services, while choreography promotes the idea of smart endpoints and dump pipes, with a potential downside of introducing cycling dependencies. In choreography, microservices publish and consume messages from the message broker, which helps the overall architecture to be more scalable and fault-tolerant.

Observability

Managing, monitoring, and controlling microservices at scale is a difficult problem. You need to have good observability in place to understand the interaction and behavior of different parts of the system. You need to collect metrics, logs, call stacks, raise alerts, and implement distributed tracing to help you reason about the system.

End-to-end testing

End-to-end testing the microservices is more challenging as it requires reliable and effective communication to bring all the teams on board. End-to-end testing can also hamper your release frequency. Setting up a test environment is difficult and requires coordination across teams.

Double mortgage period

If you are migrating from a monolithic application to a microservice, then you need to live in a hybrid world for a while to support both the legacy and the new application. This is not easy and requires careful planning when it comes to fixing bugs and adding new features, thus affecting agility and productivity.

Platform investment

Organizations need to invest in platform teams that are responsible for building platform services and addressing cross-cutting concerns. These cross-cutting concerns will be covered in detail in Chapter 7, Cross-Cutting Concerns. These teams also build tools and frameworks to help other teams get the job done.

The previous sections have given us a good overview of microservices, along with their design principles, advantages, and challenges. We'll now have a look at the various architecture components of microservices and their interaction when it comes to building scalable and robust applications.

Microservice architecture components

Microservices are a loosely coupled set of services that cooperate to achieve a common goal. Besides microservices, there are other components that play a vital role in a microservice architecture. The set of components that help establish the foundation of microservices are shown in the following diagram:

Figure 1.1 – A microservice architecture with its components

The preceding diagram demonstrates the interaction of different microservice architecture components. These microservices are hosted on an orchestration platform, responsible for ensuring self-healing and the high availability of microservices. These microservices then communicate with each other using orchestration or choreography patterns. In orchestration, a microservice is responsible for invoking other microservice interfaces while in choreography, messages are exchanged using an event bus. A client can consume microservices via an API gateway, where messages are relayed to a specific microservice for actual processing. Each team has full autonomy in choosing the right storage mechanism for their microservices, as depicted in the preceding diagram, where different microservices are using a SQL database, an in-memory database, and a NoSQL database for their data storage needs.

We will discuss each component in the following sections.

Messages

Messages contain information that's needed for microservices to communicate with each other. These messages help microservice architecture be loosely coupled. Messages are further classified as commands or events. Commands usually contain more information for the recipient, with the expectation of then being notified about the delivery of messages. Events are lightweight and are mainly used as notification mechanisms, without any expectations from the consumer. These messages can be synchronous or asynchronous.

Persistence and state management

Data handling is an important aspect of microservices. Most of the microservices need to persist data/state. In a microservice architecture, data is decentralized, where every microservice