25,19 €
Learn the essential concepts, techniques, and design patterns that will help you build scalable and maintainable distributed systems
The microservice architectural style promotes the development of complex applications as a suite of small services based on specific business capabilities. With this book, you'll take a hands-on approach to build microservices and deploy them using ASP .NET Core and Microsoft Azure.
You'll start by understanding the concept of microservices and their fundamental characteristics. This microservices book will then introduce a real-world app built as a monolith, currently struggling under increased demand and complexity, and guide you in its transition to microservices using the latest features of C# 8 and .NET Core 3. You'll identify service boundaries, split the application into multiple microservices, and define service contracts. You'll also explore how to configure, deploy, and monitor microservices using Docker and Kubernetes, and implement autoscaling in a microservices architecture for enhanced productivity. Once you've got to grips with reactive microservices, you'll discover how keeping your code base simple enables you to focus on what's important rather than on messy asynchronous calls. Finally, you'll delve into various design patterns and best practices for creating enterprise-ready microservice applications.
By the end of this book, you'll be able to deconstruct a monolith successfully to create well-defined microservices.
This book is for C# and .NET Core developers who want to understand microservices architecture and implement it in their .NET Core applications. If you’re new to building microservices or have theoretical knowledge of the architectural approach, this book will help you gain a practical perspective to manage application complexity efficiently.
Gaurav Aroraa is a serial entrepreneur and start-up mentor. He has done an M.Phil in computer science. He is a Microsoft MVP award recipient. He is a lifetime member of the Computer Society of India (CSI), is an advisory member and senior mentor at IndiaMentor, is certified as a Scrum trainer/coach, is ITIL-F certified, and is PRINCE-F and PRINCE-P certified. He is an open source developer and a contributor to the Microsoft TechNet community. Recently, Gaurav was awarded "Icon of the year – excellence in Mentoring Technology Startups" for 2018-19 by Radio City, a Jagran initiative, for his extraordinary work during his 22-year career in the industry in the field of technology mentoring. Ed Price is a senior program manager in engineering at Microsoft, with an MBA in technology management. He has run Microsoft customer feedback programs for Azure Development, Service Fabric, IoT, and Visual Studio. He was also a technical writer at Microsoft for 6 years, helped to lead TechNet Wiki, and now leads efforts to publish key guidance from AzureCAT (Customer Advisory Team), especially in the development of microservices. He is the coauthor of Learn to Program with Small Basic.Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 530
Veröffentlichungsjahr: 2020
Copyright © 2020 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.
Commissioning Editor: Richa TripathiAcquisition Editor: Denim PintoContent Development Editor: Tiksha Abhimanyu LadSenior Editor: Afshaan KhanTechnical Editor: Romy DiasCopy Editor: Safis EditingProject Coordinator:Francy PuthiryProofreader: Safis EditingIndexer: Priyanka DhadkeProduction Designer: Nilesh Mohite
First published: June 2017 Second edition: December 2017 Third edition: March 2020
Production reference: 2100620
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78961-794-8
www.packt.com
Packt.com
Subscribe to our online digital library for full access to over 7,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Fully searchable for easy access to vital information
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.packt.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.packt.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Microservices is more than just a buzzword. They represent a fresh new way of thinking about systems architecture that builds upon the designs and layering of the last two decades, combined with the real-world experiences of building large scalable systems at a size we once thought impossible.
We've all learned about three-tiered architecture: we design our systems with the single responsibility principle, and we have tried different ways to scale and deploy our systems. Microservices combines the best of all these worlds. It aims to build systems that separate responsibility appropriately; that manage, version, and deploy services individually; and that elastically scale, backed by the power of the cloud.
This new generation of cloud-native applications needed a new way of thinking about architecture. Gaurav and Ed have put together a journey that walks you through the process of creating effective microservices, using C# 8 and the new open source, cross-platform .NET Core.
The book covers everything that you'll need, from architecture, an introduction to containers, and how services communicate, to the concepts behind a service mesh. Everything is backed by practical examples in real-world use cases, including IoT.
I'm thrilled that you're coming along this journey with us, and I'm excited to see what you'll be able to build with this new knowledge.
Scott Hanselman Partner Program Manager .NET Open Source
Gaurav Aroraa is a serial entrepreneur and start-up mentor. He has done an M.Phil in computer science. He is a Microsoft MVP award recipient. He is a lifetime member of the Computer Society of India (CSI), is an advisory member and senior mentor at IndiaMentor, is certified as a Scrum trainer/coach, is ITIL-F certified, and is PRINCE-F and PRINCE-P certified. He is an open source developer and a contributor to the Microsoft TechNet community. Recently, Gaurav was awarded "Icon of the year – excellence in Mentoring Technology Startups" for 2018-19 by Radio City, a Jagran initiative, for his extraordinary work during his 22-year career in the industry in the field of technology mentoring.
Ed Price is a senior program manager in engineering at Microsoft, with an MBA in technology management. He has run Microsoft customer feedback programs for Azure Development, Service Fabric, IoT, and Visual Studio. He was also a technical writer at Microsoft for 6 years, helped to lead TechNet Wiki, and now leads efforts to publish key guidance from AzureCAT (Customer Advisory Team), especially in the development of microservices. He is the coauthor of Learn to Program with Small Basic.
Andreas Helland has a degree in software engineering and over 20 years of experience in building products and services. He has worked both with the development side and the infrastructure side and holds a number of Microsoft certifications across various skill sets. This also led him to become an early adopter of Azure. After building up his knowledge working in the telecommunications industry, he switched to consulting, and currently works as an architect for Capgemini where he assists customers on how to utilize the cloud in the best ways possible. He specializes in Azure Active Directory and works closely with the Identity teams at Microsoft, both in testing new services and providing feedback based on learnings from the field.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
Hands-On Microservices with C# 8 and .NET Core 3 Third Edition
Dedication
Packt Upsell
Why subscribe?
Foreword
Contributors
About the authors
About the reviewer
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
An Introduction to Microservices
Technical requirements
The origin of microservices
Discussing microservices
Exploring monolithic architecture
Service-oriented architecture
Understanding services
Understanding microservice architecture
Messaging in microservices
Synchronous messaging
Asynchronous messaging
Message formats
Using microservices
The workings of microservice architecture
The advantages of microservices
SOA versus microservices
The prerequisites of microservice architecture
Understanding the problems with the monolithic architectural style
The challenges in standardizing a .NET stack
Fault tolerance
The scaling property of a system
Vertical scaling or scale-up
Horizontal scaling or scale-out
Deployment challenges
Organizational alignment
Modularity
Big database
Prerequisites for microservices
Functional overview of the application
Solutions for the current challenges
Handling deployment problems
Making better monolithic applications
Introducing dependency injections
Database refactoring
Database sharding and partitioning
DevOps culture
Automation
Testing
Versioning
Deployment
Identifying decomposition candidates within monolithic
Important microservices advantages
Technology independence
Interdependency removal
Alignment with business goals
Cost benefits
Easy scalability
Security
Data management
Integrating monolithic applications with microservices
An overview of Azure Service Fabric
Summary
Questions
Refactoring the Monolith
Technical requirements
Understanding the current and new technology stack
Discussion – current stack (C#, EF, and SQL Server)
C# 8
Entity Framework Core
Visual Studio 2019
Microsoft SQL Server
New features in .NET Core 
New features in C# 8.0
Enabling support for the C# 8.0 language using Visual Studio
Indices and ranges
The readonly members
Default interface methods
The size of microservices
What makes a good service?
DDD and its importance for microservices
Domain model design
Importance for microservices
Understanding the concept of seam
Module interdependency
Technology
Team structure
Databases
Master data
Transactions
Communication between microservices
The benefits of the API gateway for microservices
API gateway versus API management
Revisiting the FlixOne case study
Prerequisites
Transitioning to our product service
Migrations
Code migration
Creating our project
Adding the model
Adding a repository
Registering repositories
Adding a product controller
The ProductService API
Adding EF Core support
EF Core DbContext
EF Core migrations
Database migration
Revisiting repositories and the controller
Introducing ViewModel
Revisiting ProductController
Adding Swagger support
Summary
Questions
Further reading
Effective Communication between Services
Technical requirements
Understanding communication between services
Styles of collaboration
Learning about integration patterns
The API gateway
The event-driven pattern
Event-sourcing pattern
Eventual consistency pattern
Compensating transactions
Competing consumers
Understanding Azure Service Fabric
Service Fabric architecture
Discussing the orchestrator
Service Fabric programming models overview
Implementing information on competing consumers
Azure Service Bus
Azure message queues
Implementing information on Service Fabric
Prerequisites
Sending messages to the queue
Adding configuration settings
Receiving messages from the queue
Implementing information on containers
Containers on Service Fabric
Prerequisites
Execution
Microservices with Kubernetes
An overview of Azure Kubernetes Service (AKS)
Important concepts
Ease of deploying and managing microservices
The sidecar pattern
When to use the sidecar pattern
Best practices to be observed
The ambassador pattern
When to use the ambassador pattern
Best practices to be observed
Considering IoT when building microservices apps
An overview of IoT Hub
An overview of IoT Edge
Summary
Questions
Further reading
Testing Microservices with the Microsoft Unit Testing Framework
Technical requirements
Testing the microservice application
Handling testing challenges with microservices
Understanding testing strategies
Testing pyramid
Types of microservice tests
Unit testing
Component (service) testing
Integration testing
Contract testing
Consumer-driven contracts
How to implement a consumer-driven test
How Pact-net-core helps us achieve our goal
Performance testing
End-to-end (UI/functional) testing
Sociable versus isolated unit tests
Stubs and mocks
Testing the microservice application
Getting ready for the test project
Unit tests
Integration tests
Summary
Questions
Further reading
Deploying Microservices with Docker
Technical requirements
Monolithic application deployment challenges
Understanding the deployment terminology
Prerequisites for successful microservice deployments
Isolation requirements for microservice deployment
The need for a new deployment paradigm
The way out – containers
What are containers?
Suitability of containers over virtual machines
Transformation of the operation team's mindset 
Containers are new binaries
Does it work on your machine? Let's ship your machine!
Introducing Docker
Deploying a sample application
Microservice deployment example using Docker
Setting up Docker on your machine
Prerequisites
Creating an ASP.NET Core web application
Summary
Questions
Further reading
Securing Microservices Using Azure Active Directory
Technical requirements
Security in monolithic applications
Security in microservices
Why won't a traditional .NET auth mechanism work?
JSON Web Tokens
Working with OAuth 2.0
Exploring OpenID Connect
Understanding Azure Active Directory
Microservice Auth example with OpenID Connect, OAuth 2.0, and Azure AD
Registering our application with the Azure AD tenant
Generating AppKey for FlixOne.BookStore.Web
Configuring Visual Studio solution projects
Generating client certificates on IIS Express
Running both applications
Managing Azure API Management as an API gateway
An example of a rate limit and quota policy
Understanding container security
Other security best practices
Summary
Questions
Further reading 
Monitoring Microservices
Technical requirements
Setting up .NET Core 3.1
A valid Azure account
Beginning with instrumentation and telemetry
Instrumentation
Telemetry
The need for monitoring
Health monitoring
Availability monitoring
SLA monitoring
Performance monitoring
Security monitoring
Auditing sensitive data and critical business transactions
End user monitoring
Troubleshooting system failures
Understanding the monitoring challenges
Scaling issues
DevOps mindset
Data flow visualization
Testing monitoring tools
Working on monitoring strategies
Application/system monitoring
Real user monitoring
Semantic monitoring and synthetic transactions
Profiling
Endpoint monitoring
Understanding logging
Logging challenges
Logging strategies
Centralized logging
Using a correlation ID in logging
Semantic logging
Monitoring on Azure
Microsoft Azure Diagnostics
Storing diagnostic data using Azure storage
Using the Azure portal
Defining an Azure storage account
Azure storage schema for diagnostic data
Introduction to Application Insights
Monitoring our FlixOne application
Other microservice monitoring solutions
A brief overview of the ELK stack
Elasticsearch
Logstash
Kibana
Splunk
Alerting
Reporting
Summary
Questions
Further reading
Scaling Microservices with Azure
Technical requirements
Getting an overview of scalability
Scaling infrastructure
Vertical scaling (scaling up)
Horizontal scaling (scaling out)
Understanding microservice scalability
The Scale Cube model of scalability
Scaling of the x axis
Scaling of the z axis
Scaling of the y axis 
Characteristics of a scalable microservice
Implementing scaling infrastructure
Scaling virtual machines using scale sets
Autoscaling
Container scaling using Docker Swarm
Scaling service design
Data persistence model design
Caching mechanism
CacheCow
Azure Cache for Redis
Redundancy and fault tolerance
Circuit breakers
Closed state
Open state
Half-Open state
Service discovery
Summary
Questions
Further reading
Introduction to Reactive Microservices
Technical requirements
Installing Visual Studio 2019
Understanding reactive microservices
Responsiveness
Resilience
Autonomy
Message-driven – a core of reactive microservices
Making code reactive
Understanding event communication
Security
Message-level security
Scalability
Communication resilience
Managing data
Trying out the coding of reactive microservices
Creating the project
Communicating between the application and the database
Client – coding it down
Summary
Questions
Further reading
Design Patterns and Best Practices
Technical requirements
Installing Visual Studio 2019
The Aggregator pattern
Pros and cons
Best practices to be observed
The problem and its solution – example in FlixOne
Implementing the solution
The Common folder
The Controllers folder
The Models folder 
The Persistence folder
The Services folder
The Shared Data microservices pattern
Pros and cons of the pattern
Best practices to be observed
The problem and its solution – example in FlixOne
Implementing the solution
The Extensions folder
The Models folder
The Persistence folder
The Controllers folder
The Anti-Corruption Layer pattern
Pros and cons
Best practices to be observed
Problem and its solution – the need for the Anti-Corruption Layer pattern
Implementing the solution
The BL folder
The Models folder
The DAL folder
The Contexts folder
The Repository folder
The Services folder
The Controllers folder
Summary
Further reading
Building a Microservice Application
Technical requirements
Installing Visual Studio 2019
Setting up Azure
Revisiting the monolithic architecture style and SOA
Introducing the strangler pattern
Understanding the business needs of an application
Revisiting the application
Building the application
Summary
Microservices Architecture Summary
Technical requirements
Understanding architectures before microservices
Monolithic architecture
Challenges in standardizing the .NET stack
Scaling
Service-oriented architecture 
Microservice-style architecture
Messaging in microservices
Understanding how monolith transitioning works
Integration techniques
Deployment
Testing microservices
Security
Monitoring the application
Monitoring challenges
Scale
Component lifespan
Information visualization
Understanding monitoring strategies
Understanding scalability
Infrastructure scaling
Service design
An overview of reactive microservices
Building a greenfield application
Scoping our services
The book-listing microservice
The book-searching microservice
The shopping-cart microservice
The order microservice
User authentication
Synchronous versus asynchronous
The book-catalog microservice
The shopping-cart microservice
The order microservice
The user-authentication microservice
An overview of cloud-native microservices
Summary
Appendix
API Gateway pattern
Adapting the API Gateway on the basis of its pros and cons
Preferred practices while implementing the API Gateway
Implementing the API Gateway
Preferring Ocelot
Initial steps
Aggregation
Logging
Protecting services from attacks by defining rate-limits
Implementing security services
Backends for Frontends pattern
Assessments
Chapter 1
Chapter 2
Chapter 3
Chapter 4
Chapter 5
Chapter 6
Chapter 7
Chapter 8
Chapter 9
Other Books You May Enjoy
Leave a review - let other readers know what you think
The purpose of this book is to give you a broad understanding of microservices in modern software development while also diving into more detail with specific examples using .NET Core APIs. This book covers the theory of microservices followed by a high-level understanding of the patterns used to develop an imaginary application, where we'll cover the concepts used in solutions that can be easily configured to run in the cloud or on-premises.
Notably, microservice architecture does have critical advantages—particularly in regard to empowering the agile improvement and conveyance of complex venture applications.
However, there is no clear or practical advice on how to implement microservices in the Microsoft ecosystem, especially on how to take advantage of Azure and the .NET Core framework. This book tries to fill that void.
Although many aspects of the microservice architecture do not require a detailed explanation, we try to sum up these concepts and provide Microsoft docs links for further reading. Throughout the book, until we start developing our imaginary application, we will cover every part that is required to develop a microservice architecture-based application.
Starting with a simple API project and monolith application, the book describes various steps that you can perform to transition to microservices. To make the code examples simpler, the book uses .NET Core APIs throughout. The last chapter includes an application that shows the crux of the complete book.
The target audience of this book includes application developers who want to find a one-stop shop of best practices for architecting a high-performing application in the Azure cloud. This book applies to all developers of Azure. It is also aimed at developers who want to learn about and understand microservice architecture and implement it in their .NET Core applications. This book has been written/updated in such a way that novice-to-advanced-level users will be covered. It's ideal for developers who are completely new to microservices or only have a theoretical understanding of this architectural approach and want to gain a practical perspective in order to better manage the complexity of their application.
Chapter 1, An Introduction to Microservices, discusses the basics of microservices, reviews a monolith application, and uncovers its limitations. You will also learn how to start the transition to a microservices architecture.
Chapter 2, Refactoring the Monolith, discusses the current stack of the application. It also covers the features of .NET Core and C#8, demonstrates how to implement separate microservices, and looks at communication between microservices.
Chapter 3, Effective Communication between Services, covers communication between services, including synchronous and asynchronous communication, and an overview of Azure Service Bus. Additionally, the chapter examines integration with the help of an integration pattern. An overview of Azure Service Fabric is followed by a look at Docker and containers, as well as an overview of Azure Kubernetes Service, IoT Hub, and IoT Edge.
Chapter 4, Testing Microservices with the Microsoft Unit Testing Framework, covers various types of services and their differences. Here you will implement testing approaches using the Microsoft Unit Testing Framework, Moq, and the ASP.NET Core API.
Chapter 5, Deploying Microservices with Docker, covers the deployment paradigm and explains deployment terminology.
Chapter 6, Securing Microservices Using Azure Active Directory, uncovers the concept of securing microservices by deploying a sample application using Azure Active Directory.
Chapter 7, Monitoring Microservices, covers instrumentation and telemetry, followed by monitoring strategies, logging, and monitoring in the cloud.
Chapter 8, Scaling Microservices with Azure, explores scalability, infrastructure scaling, and microservices scaling. The chapter also presents an overview of Azure Redis Cache.
Chapter 9, Introduction to Reactive Microservices, introduces you to reactive microservices with the help of code examples.
Chapter 10, Design Patterns and Best Practices, covers high-level patterns to help build microservices, as well as Aggregator, DDD, API gateways, the Shared Data microservices pattern, the anti-corruption layer pattern, and BFF.
Chapter 11, Building a Microservice Application, examines the various approaches that are available to develop a real-world application.
Chapter 12, Microservices Architecture Summary, looks at how applications could evolve in the future by following the microservices approach.
Appendix, explains about the API Gateway pattern and the Backends to Frontends pattern, in terms of their pros and cons, to help us understand their best practices.
This book assumes that you have some familiarity with SOA, RESTful web services, APIs, server/client architectures, .NET Core, ASP.NET Core, and C#. This book covers advanced topics, basic concepts, and an overview of technologies such as Kubernetes and IoT Edge. The book's contents are designed to get you started with the development of a microservices-based application. It can also be used as a comprehensive guide. Using a toolbox analogy, the book provides a large number of tools for the modern application developer, progressing from low-level code design to higher-level architecture, as well as important concepts, patterns, and best practices commonly used today for the development of microservices-based applications. This book will cover the following main points:
The details of microservices, including in-depth details of monolith versus SOA versus microservices architectures
Examples using C#8 and ASP.NET Core 3
An overview of the current application stack and the new stack to develop microservices via an imaginary application
In-depth discussion of design patterns and best practices using demo application
You need to install Visual Studio 2019 (Community edition preferably) with the latest update. All code examples have been tested using .NET Core 3.1 on Windows OS. However, they should work with future version releases too.
Software/Hardware covered in the book
OS requirements
ASP.NET Core 3.1
Windows
C# 8
Windows
SQL Server 2008R2
Windows
SQL Server 2017
Windows
If you are using the digital version of this book, we advise you to type the code yourself or access the code via the GitHub repository (link available in the next section). Doing so will help you avoid any potential errors related to copy/pasting of code.
You can download the example code files for this book from your account at www.packt.com. If you purchased this book elsewhere, you can visit www.packt.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packt.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Hands-On-Microservices-with-CSharp-8-and-.NET-Core-3-Third-Edition. In case there's an update to the code, it will be updated on the existing GitHub repository.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://static.packt-cdn.com/downloads/9781789617948_ColorImages.pdf
Feedback from our readers is always welcome.
General feedback: If you have questions about any aspect of this book, mention the book title in the subject of your message and email us at [email protected].
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.packt.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
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.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packt.com.
The focus of this chapter is to get you acquainted with microservices. Slicing your application into a number of services is neither a feature of service-oriented architecture (SOA) nor microservices. However, microservices combines service design with best practices from the SOA world, along with a few emerging practices, such as isolated deployment, semantic versioning, providing lightweight services, and service discovery in polyglot programming. We implement microservices to satisfy business features, reducing the time to market and increasing flexibility.
We will cover the following topics in this chapter:
The origin of microservices
Discussing microservices
Understanding the microservice architecture
The advantages of microservices
SOA versus microservices
Understanding the problems with the monolithic architectural style
The challenges in standardizing a .NET stack
An overview of Azure Service Fabric
In this chapter, we will become familiar with the problems that arise from having a layered monolithic architecture. We will also discuss the solutions available for these problems in the monolithic world. By the end of the chapter, we will be able to break down a monolithic application into a microservice architecture.
This chapter contains various code examples to explain the concepts. The code is kept simple and is just for demo purposes.
To run and execute the code, you will need the following prerequisites:
Visual Studio 2019
.NET Core 3.1
To install and run these code examples, you need to install Visual Studio 2019 (the preferred IDE). To do so, download Visual Studio 2019 (the Community edition, which is free) from the download link mentionedin the installation instructions:https://docs.microsoft.com/en-us/visualstudio/install/install-visual-studio.Multiple versions are available for the Visual Studio installation. We are using Visual Studio for Windows.
If you do not have .NET Core 3.1 installed, you can download it from the following link: https://www.microsoft.com/net/download/windows.
Before we discuss the details, we should explore the origin of microservices or any new framework, language, and so on. Microservices is a buzzword, and we should be aware of how this architectural style evolved to the point that it is now trending. There are several reasons to familiarize yourself with the origin of any language or framework. The most important things to know are as follows:
How the specific language or framework came into context.
Who is behind the new trending architectural style of microservices?
What and where it was founded.
Now let's discuss the origin of microservices. The term microservices was used for the first time in mid-2011 at a workshop for software architects. In March 2012, James Lewis presented some of his ideas about microservices. By the end of 2013, various groups from the IT industry started having discussions about microservices, and by 2014, the concept had become popular enough to be considered a serious contender for large enterprises.
There is no official definition available for microservices. The understanding of the term is purely based on use cases and discussions held in the past.
In 2014, James Lewis and Martin Fowler came together and provided a few real-world examples as well as presenting microservices (refer to http://martinfowler.com/microservices/).
The official Microsoft document page for microservices (refer tohttps://docs.microsoft.com/en-us/azure/architecture/guide/architecture-styles/microservices) defines the microservices architectural style as follows:
It is very important that you see all the attributes Lewis and Fowler defined here. They defined microservices as an architectural style that developers can utilize to develop a single application with the business logic spread across a bunch of small services, each having their own persistent storage functionality. Also, note its attributes: it can be independently deployable, can run in its own process, is a lightweight communication mechanism, and can be written in different programming languages.
We want to emphasize this specific definition since it is the crux of the whole concept. As we move along, all the pieces will fit together by the time we finish this book. For now, we will look at microservices in detail.
We have gone through a few definitions of microservices; now let's discuss them in detail.
In short, a microservice architecture removes most of the drawbacks of SOA. It is also more code-oriented than SOA services (we will discuss this in detail in the coming sections).
Before we move on to understanding the architecture, let's discuss the two important architectures that led to its existence:
The monolithic architecture style
SOA
Most of us know that when we develop an enterprise application, we have to select a suitable architectural style. Then, at various stages, the initial pattern is further improved and adapted with changes that cater to various challenges, such as deployment complexity, a large code base, and scalability issues. This is exactly how the monolithic architecture style evolved into SOA, and then led to microservices.
The monolithic architectural style is a traditional architecture type that has been widely used in the IT industry. The term monolithic is not new and is borrowed from the Unix world. In Unix, most commands exist as a standalone program whose functionality is not dependent on any other program. As seen in the following diagram, we can have different components in the application, including the following:
User interface
: This handles all of the user interactions while responding with HTML, JSON, or any other preferred data interchange format (in the case of web services).
Business logic
: This includes all the business rules applied to the input being received in the form of user input, events, and the database.
Database access
: This houses the complete functionality for accessing the database for the purpose of querying and persisting objects. A widely accepted rule is that it is utilized through business modules and never directly through user-facing components.
Software built using this architecture is self-contained. We can imagine a single .NET assembly that contains various components, as depicted in the following diagram:
As the software is self-contained here, its components are interconnected and interdependent. Even a simple code change in one of the modules may break a major functionality in other modules. This would result in a scenario in which we'd need to test the whole application. With the business depending critically on its enterprise application frameworks, this amount of time could prove to be very critical.
Having all the components tightly coupled poses another challenge: whenever we execute or compile such software, all the components should be available or the build will fail. Refer to the previous diagram, which represents a monolithic architecture and is a self-contained or a single .NET assembly project. However, monolithic architectures might also have multiple assemblies. This means that even though a business layer (assembly, data access layer assembly, and so on) is separated, all of them will come together and run as one process at runtime.
A user interface depends on other components' direct sales and inventory in a manner similar to all other components that depend upon each other. In this scenario, we would not be able to execute this project in the absence of any one of these components. The process of upgrading them would be more complex, as we would have to consider other components that require code changes too. This would result in more development time than is required for the actual change.
Deploying such an application would become another challenge. During deployment, we would have to make sure that every component was deployed properly. If we didn't do this, we may end up facing a lot of issues in our production environments.
If we develop an application using the monolithic architecture style, as discussed previously, we might face the following challenges:
Large code base
: This is a scenario where the code lines outnumber the comments by a great margin. As components are interconnected, we would have to deal with a repetitive code base.
Too many business modules
: This is in regard to modules within the same system.
Code base complexity
: This results in a higher chance of code breaking due to the fix required in other modules or services.
Complex code deployment
: You may come across minor changes that would require whole system deployment.
One module failure affecting the whole system
: This is with regard to modules that depend on each other.
Scalability
: This is required for the entire system and not just the modules in it.
Intermodule dependency
: This is due to tight coupling. This results in heavy changes if required for an operation of any of the modules.
Spiraling development time
: This is due to code complexity and interdependency.
Inability to easily adapt to new technology
: In this case, the entire system would need to be upgraded.
As discussed earlier, if we want to reduce development time, ease deployment, and improve the maintainability of software for enterprise applications, we should avoid traditional or monolithic architecture. Therefore, we will look at SOA.
In the previous section, we discussed the monolithic architecture and its limitations. We also discussed why it does not fit into our enterprise application requirements. To overcome these issues, we should take a modular approach where we can separate the components so that they come out of the self-contained or single .NET assembly. A system that uses a service or multiple services in the fashion depicted in the previous diagram is called a service-oriented architecture (SOA).
Let's discuss modular architecture, that is, SOA. This is a famous architectural style where enterprise applications are designed as a collection of services. These services may be RESTful or ASMX web services. To understand SOA in more detail, let's discuss services first.
Services, in this case, are an essential concept of SOA. They can be a piece of code, a program, or software that provides functionality to other system components. This piece of code can interact directly with the database or indirectly through another service. Furthermore, it can be consumed by clients directly, where the client may be a website, desktop app, mobile app, or any other device app. The following diagram shows that services can be consumed by various clients via the web, desktop, mobile, or any other devices. Services can be with or without database support at the backend:
A service refers to a type of functionality exposed for consumption by other systems (generally referred to as clients/client applications). As mentioned earlier, this can be represented by a piece of code, a program, or software. Such services are exposed over the HTTP transport protocol as a general practice. However, the HTTP protocol is not a limiting factor, and a protocol can be picked as deemed fit for the scenario.
In the following diagram, Service - direct selling is directly interacting with the Database and three different clients, namely, Web, Desktop, and Mobile, are consuming the service. On the other hand, we have clients consuming Service - partner selling, which is interacting with Service - channel partners for database access.
A product selling service is a set of services that interact with client applications and provide database access directly or through another service, in this case, Service – Channel partners. In the case of Service – direct selling, shown in the following diagram, it is providing the functionality to a web store, a desktop application, and a mobile application. This service is further interacting with the database for various tasks, namely, fetching and persisting data.
Normally, services interact with other systems via a communication channel, generally the HTTP protocol. These services may or may not be deployed on the same or single servers:
In the previous diagram, we have projected an SOA example scenario. There are many fine points to note here, so let's get started. First, our services can be spread across different physical machines. Here, Service - direct selling is hosted on two separate machines. It is possible that instead of the entire business functionality, only a part of it will reside on Server 1 and the remaining part on Server 2. Similarly, Service - partner selling appears to have the same arrangement on Server 3 and Server 4. However, it doesn't stop Service - channel partners from being hosted as a complete set on both Server 5 and Server 6.
We will discuss SOA in detail in the following sections.
Let's recall monolithic architecture. In this case, we did not use it because it restricts code reusability; it is a self-contained assembly, and all the components are interconnected and interdependent. For deployment, in this case, we will have to deploy our complete project after we select the SOA (refer to the previous diagram and the subsequent discussion). Now, because of the use of this architectural style, we have the benefit of code reusability and easy deployment. Let's examine this in the light of the previous diagram:
Reusability
: Multiple clients can consume the service. This can also be simultaneously consumed by other services. For example,
OrderService
is consumed by web and mobile clients.
OrderService
can now also be used by the Reporting Dashboard UI.
Stateless
: Services do not persist in any state between requests from the client. This means that the service doesn't know or care that the subsequent request has come from the client that has/hasn't made the previous request.
Contract-based:
Interfaces make any service technology-agnostic on both sides of implementation and consumption. They also serve to make it immune to the code updates in the underlying functionality.
Scalability
: A system can be scaled up, and the SOA can be individually clustered with the appropriate load balancing.
Upgradeability
: It is very easy to roll out new functionalities or introduce new versions of the existing functionality. The system doesn't stop you from keeping multiple versions of the same business functionality.
This section covered SOA, and we have also discussed the concept of services and how they impact architecture. Next, we will move on to learn all about microservice architecture.
Microservice architecture is a way to develop a single application containing a set of smaller services. These services are independent of each other and run in their own processes. An important advantage of these services is that they can be developed and deployed independently. In other words, we can say that microservices are a way to segregate our services so that they can be handled completely independently of each other in the context of design, development, deployment, and upgrades.
In a monolithic application, we have a self-contained assembly of a user interface, direct sales, and inventory. In microservice architecture, the parts of the services of the application change to the following depiction:
Here, business components have been segregated into individual services. These independent services are now the smaller units that existed earlier within the self-contained assembly in the monolithic architecture. Both direct sales and inventory services are independent of each other, with the dotted lines depicting their existence in the same ecosystem, not yet bound within a single scope.
Refer to the following diagram, depicting user interaction with different APIs:
From the previous diagram, it's clear that our user interface can interact with any services. There is no need to intervene with any service when a UI calls it. Both services are independent of each other, without being aware of when the other one would be called by the user interface. Both services are liable for their own operations and not for any other part of the whole system. Although we are much closer to the layout of our intended microservice architecture. Note that the previous representation of the layout is not entirely a complete visualization of the intended microservice architecture.
Now let's apply this final change so that each service will have its own database persisting the necessary data. Refer to the following diagram:
Here, the User interface is interacting with the services, which have their own independent storage. In this case, when a user interface calls the service for direct sales, the business flow for direct sales is executed independently of any data or logic contained within the inventory service.
The solution provided by the use of microservices has a lot of benefits, including the following:
A smaller code base
: Each service is small and therefore easier to develop and deploy as a unit.
The ease of an independent environment
: With the separation of services, all developers work independently, deploy independently, and no one is concerned about module dependency.
With the adoption of microservice architecture, monolithic applications are now harnessing the associated benefits, as they can now be scaled easily and deployed independently using a service.
It is very important to carefully consider the choice of messaging mechanism when dealing with microservice architecture. If this aspect is ignored, it can compromise the entire purpose of designing a microservice architecture. In monolithic applications, this is not a concern, as the business functionality of the components gets invoked through function calls. On the other hand, this happens via a loosely coupled web service-level messaging feature in which services are primarily based on SOAP. In the case of the microservice messaging mechanism, this should be simple and lightweight.
There are no set rules for making a choice between the various frameworks or protocols for microservice architecture. However, there are a few points worth considering here. First, it should be simple enough to implement, without adding any complexity to your system. Second, it should be very lightweight, keeping in mind the fact that the microservice architecture could heavily rely on interservice messaging. Let's move ahead and consider our choices for both synchronous and asynchronous messaging, along with the different messaging formats.
Synchronous messaging is when a timely response is expected from service by a system, and the system waits until a response is received from the service. What's left is the most sought-after choice in the case of microservices. This is simple and supports an HTTP request-response, thereby leaving little room to look for an alternative. This is also one of the reasons that most implementations of microservices use HTTP (API-based styles).
Asynchronous messaging is when a system does not immediately expect a timely response from the service, and the system can continue processing without blocking that call.
Let's incorporate this messaging concept into our application and see how it would change the working and look of our application:
In the preceding diagram, the user would get a response while the system is interacting with the Sales DB and/or Inventory DB service(s) and fetch or push the data to their respective databases. The calls from the user (via theUser interface) to respective services would not block new calls from the same or different users.
Over the past few years, working with MVC and the like has got me hooked on the JSON format. You could also consider XML. Both formats would be fine on HTTP with the API style resource. Binary message formats are also available if you need to use one. We are not recommending any particular format; you can go ahead with your preferred message format.
Tremendous patterns and architectures have been explored by the community, with some gaining popularity. With each solution having its own advantages and disadvantages, it has become increasingly important for companies to quickly respond to fundamental demands, such as scalability, high performance, and easy deployment. Any single aspect failing to be fulfilled in a cost-effective manner could easily impact large businesses negatively, making a big difference between a profitable and a non-profitable venture.
With the help of this architectural style, stakeholders can ensure that their designs are protected against the problems mentioned previously. It is also important to consider the fact that this objective is met in a cost-effective manner while respecting the time involved.
Let's see how microservice architecture works.
Microservice architecture is an architectural style that structures an application as a collection of loosely coupled services. These services can intercommunicate or be independent of each other. The overall working architecture of a microservice-based application depends on the various patterns that are used to develop the application. For example, microservices could be based on backend or frontend patterns. We will discuss various patterns in Chapter 10, Design Patterns and Best Practices.
Up until this point, we have discussed variousaspects of microservice architecture, and we can now depict how it works; we can use any combination according to our design approach or predict a pattern that would fit.Here are some benefits of working with microservice architecture:
In the current era of programming, everyone is expected to follow all of the SOLID principles. Almost all languages are
object-oriented programming
(
OOP
).
It is the best way is to expose functionality to other, or external, components in a way that allows any other programming language to use that functionality without adhering to any specific user interfaces (that is, services such as web services, APIs, REST services, and so on).
The whole system works according to a type of collaboration that is not interconnected or interdependent.
Every component is liable for its own responsibilities. In other words, components are responsible for only one functionality.
It segregates code with a separation concept, and segregated code is reusable.
Now let's explore and discuss various factors as advantages of microservices over the SOA and monolithic architectures:
Cost-effective to scale
: You don't need to invest a lot to make the entire application scalable. In terms of a shopping cart, we could simply load balance the product search module and the order-processing module while leaving out less frequently used operational services, such as inventory management, order cancellation, and delivery confirmation.
Clear code boundaries
: The code should match an organization's departmental hierarchies. With different departments sponsoring product development in large enterprises, this can be a huge advantage.
Easier code changes
: The code is done in a way that is not dependent on the code of other modules and only achieves isolated functionality. If done right, then the chances of a change in a microservice affecting another microservice are minimal.
Easy deployment
: Since the entire application is more like a group of ecosystems that are isolated from each other, deployment can be done one microservice at a time, if required. Failure in any one of these would not bring the entire system down.
Technology adaptation
: You could port a single microservice or a whole bunch of them overnight to a different technology, without your users even knowing about it. Remember to maintain those service contracts.
Distributed system
: The meaning is implied here, but a word of caution is necessary. Make sure that your asynchronous calls are used well and synchronous ones are not really blocking the whole flow of information. Use data partitioning well. We will come to this a little later, in the
Data partition
section of this chapter
, so don't worry for now.
Quick market response
: The world being competitive is a definite advantage. Users tend to quickly lose interest if you are slow to respond to new feature requests or the adoption of new technology within your system.
So far, we have covered SOA and microservice architecture. We have discussed each in detail. We also saw how each is independent. In the next section, we will understand the differences between microservices and SOA.
You'll get confused between microservices and SOA if you don't have a complete understanding of both. On the surface, the microservice features and advantages sound almost like a slender version of SOA, with many experts suggesting that there is, in fact, no need for an additional term such as microservices and that SOA can fulfill all the attributes laid out by microservices. However, this is not the case. There are enough differences to isolate them technologically.
The underlying communication system of SOA inherently suffers from the following problems:
The fact that a system developed in SOA depends upon its components, which are interacting with each other. So, no matter how hard you try, it is eventually going to face a bottleneck in the message queue.
Another focal point of SOA is imperative monogramming. With this, we lose the path to make a unit of code reusable with respect to OOP.
We all know that organizations are spending more and more on infrastructure. The bigger the enterprise is, the more complex the question of the ownership of the application being developed. With an increasing number of stakeholders, it becomes impossible to accommodate all of their ever-changing business needs.
This is where microservices clearly stand apart. Although cloud development is not in the current scope of our discussion, it won't harm us to say that the scalability, modularity, and adaptability of microservice architecture can be easily extended with the use of cloud platforms. It's time for a change.
Let's look at the prerequisites of microservice architecture.
It is important to understand the resulting ecosystem from a microservice architecture implementation. The impact of microservices is not just pre-operational in nature. The changes in any organization opting for microservice architecture are so profound that if they are not well prepared to handle them, it won't be long before advantages turn into disadvantages.
After the adoption of microservice architecture is agreed upon, it would be wise to have the following prerequisites in place:
Deployment and QA
: Requirements will become more demanding, with a quicker turnaround from development requirements. This will require you to deploy and test as quickly as possible. If it is just a small number of services, then this will not be a problem. However, if the number of services is increasing, it could very quickly challenge the existing infrastructure and practices. For example, your QA and staging environment may no longer suffice to test the number of builds that come back from the development team.
A collaboration platform for the development and operations team
: As the application goes to the public domain, it won't be long before the age-old script of development versus QA is played out again. The difference this time would be that the business would be at stake. So, you need to be prepared to quickly respond in an automated manner to identify the root cause when required.
A monitoring framework
: With the increasing number of microservices, you will quickly need a way to monitor the functioning and health of the entire system for any possible bottlenecks or issues. Without any means of monitoring the status of the deployed microservices and the resultant business function, it would be impossible for any team to take a proactive deployment approach.
This section explained the prerequisites of a microservice architecture-based application. With them in place, the next section will help us understand the problems with a monolithic .NET stack-based application.
In this section, we will discuss all the problems with the monolithic .NET stack-based application. In a monolithic application, the core problem is this: scaling monolithic applications is difficult. The resultant application ends up having a very large code base and poses challenges with regard to maintainability, deployment, and modifications. In the coming sections, we will learn about scaling, and then we will move on to deployment challenges by following scaling properties.
In monolithic application technology, stack dependency stops the introduction of the latest technologies from the outside world. The present stack poses challenges, as a web service itself will suffer from them:
Security
: There is no way to identify the user via web services due to there being no clear consensus on a strong authentication scheme. Just imagine a banking application sending unencrypted data containing user credentials. All airports, cafes, and public places offering free Wi-Fi could easily become victims of increased identity theft and other cybercrimes.
Response time