|
NET-Microservices-Architecture-for-Containerized-NET-Applications
Document Outline - Introduction to Containers and Docker
- What is Docker?
- Comparing Docker containers with virtual machines
- A simple analogy
- Docker terminology
- Docker containers, images, and registries
- Choosing Between .NET and .NET Framework for Docker Containers
- General guidance
- When to choose .NET for Docker containers
- Developing and deploying cross platform
- Using containers for new (“green-field”) projects
- Create and deploy microservices on containers
- Deploying high density in scalable systems
- When to choose .NET Framework for Docker containers
- Migrating existing applications directly to a Windows Server container
- Using third-party .NET libraries or NuGet packages not available for .NET 7
- Using .NET technologies not available for .NET 7
- Using a platform or API that doesn’t support .NET 7
- Porting existing ASP.NET application to .NET 7
- Decision table: .NET implementations to use for Docker
- What OS to target with .NET containers
- Official .NET Docker images
- .NET and Docker image optimizations for development versus production
- During development and build
- In production
- Architecting container and microservice-based applications
- Container design principles
- Containerizing monolithic applications
- Deploying a monolithic application as a container
- Publishing a single-container-based application to Azure App Service
- Manage state and data in Docker applications
- Service-oriented architecture
- Microservices architecture
- Data sovereignty per microservice
- The relationship between microservices and the Bounded Context pattern
- Logical architecture versus physical architecture
- Challenges and solutions for distributed data management
- Challenge #1: How to define the boundaries of each microservice
- Challenge #2: How to create queries that retrieve data from several microservices
- Challenge #3: How to achieve consistency across multiple microservices
- Challenge #4: How to design communication across microservice boundaries
- Additional resources
- Identify domain-model boundaries for each microservice
- The API gateway pattern versus the Direct client-to-microservice communication
- Direct client-to-microservice communication
- Why consider API Gateways instead of direct client-to-microservice communication
- What is the API Gateway pattern?
- Main features in the API Gateway pattern
- Using products with API Gateway features
- Azure API Management
- Ocelot
- Drawbacks of the API Gateway pattern
- Additional resources
- Communication in a microservice architecture
- Communication types
- Asynchronous microservice integration enforces microservice’s autonomy
- Communication styles
- Request/response communication with HTTP and REST
- Additional resources
- Push and real-time communication based on HTTP
- Asynchronous message-based communication
- Single-receiver message-based communication
- Multiple-receivers message-based communication
- Asynchronous event-driven communication
- A note about messaging technologies for production systems
- Resiliently publishing to the event bus
- Additional resources
- Creating, evolving, and versioning microservice APIs and contracts
- Microservices addressability and the service registry
- Creating composite UI based on microservices
- Resiliency and high availability in microservices
- Health management and diagnostics in microservices
- Health checks
- Using diagnostics and logs event streams
- Orchestrators managing health and diagnostics information
- Additional resources
- Orchestrate microservices and multi-container applications for high scalability and availability
- Software platforms for container clustering, orchestration, and scheduling
- Using container-based orchestrators in Microsoft Azure
- Using Azure Kubernetes Service
- Development environment for Kubernetes
- Getting started with Azure Kubernetes Service (AKS)
- Deploy with Helm charts into Kubernetes clusters
- Additional resources
- Development process for Docker-based applications
- Development environment for Docker apps
- Development tool choices: IDE or editor
- Additional resources
- .NET languages and frameworks for Docker containers
- Development workflow for Docker apps
- Workflow for developing Docker container-based applications
- Step 1. Start coding and create your initial application or service baseline
- Set up your local environment with Visual Studio
- Additional resources
- Step 2. Create a Dockerfile related to an existing .NET base image
- Using an existing official .NET Docker image
- Additional resources
- Using multi-arch image repositories
- Multi-stage builds in Dockerfile
- Creating your base image from scratch
- Additional resources
- Step 3. Create your custom Docker images and embed your application or service in them
- Creating Docker images with Visual Studio
- Step 4. Define your services in docker-compose.yml when building a multi-container Docker application
- Working with docker-compose.yml in Visual Studio 2022
- Step 5. Build and run your Docker application
- Option A: Running a single-container application
- Using Docker CLI
- Using Visual Studio
- Option B: Running a multi-container application
- Using Docker CLI
- Using Visual Studio
- Additional resources
- A note about testing and deploying with orchestrators
- Step 6. Test your Docker application using your local Docker host
- Testing and debugging containers with Visual Studio 2022
- Testing and debugging without Visual Studio
- Additional resources
- Simplified workflow when developing containers with Visual Studio
- Using PowerShell commands in a Dockerfile to set up Windows Containers
- Designing and Developing Multi-Container and Microservice-Based .NET Applications
- Design a microservice-oriented application
- Application specifications
- Development team context
- Choosing an architecture
- eShopOnContainers: A reference application for .NET and microservices deployed using containers
- Data sovereignty per microservice
- Additional resources
- Benefits of a microservice-based solution
- Downsides of a microservice-based solution
- External versus internal architecture and design patterns
- The new world: multiple architectural patterns and polyglot microservices
- Creating a simple data-driven CRUD microservice
- Designing a simple CRUD microservice
- Implementing a simple CRUD microservice with ASP.NET Core
- Implementing CRUD Web API services with Entity Framework Core
- The data model
- Querying data from Web API controllers
- Saving data
- Dependency Injection in ASP.NET Core and Web API controllers
- Additional resources
- The DB connection string and environment variables used by Docker containers
- Implementing versioning in ASP.NET Web APIs
- Additional resources
- Generating Swagger description metadata from your ASP.NET Core Web API
- Why use Swagger?
- How to automate API Swagger metadata generation with the Swashbuckle NuGet package
- Additional resources
- Defining your multi-container application with docker-compose.yml
- A simple Web Service API container
- Using docker-compose files to target multiple environments
- Development environments
- Testing environments
- Production deployments
- Using multiple docker-compose files to handle several environments
- Overriding the base docker-compose file
- Targeting multiple environments
- How to deploy with a specific override file
- Using environment variables in docker-compose files
- Additional resources
- Building optimized ASP.NET Core Docker images
- Use a database server running as a container
- SQL Server running as a container with a microservice-related database
- Seeding with test data on Web application startup
- EF Core InMemory database versus SQL Server running as a container
- Using a Redis cache service running in a container
- Implementing event-based communication between microservices (integration events)
- Using message brokers and services buses for production systems
- Integration events
- The event bus
- Observer pattern
- Publish/Subscribe (Pub/Sub) pattern
- The middleman or event bus
- Defining an event bus interface
- Additional resources
- Implementing an event bus with RabbitMQ for the development or test environment
- Implementing a simple publish method with RabbitMQ
- Implementing the subscription code with the RabbitMQ API
- Additional resources
- Subscribing to events
- Publishing events through the event bus
- Designing atomicity and resiliency when publishing to the event bus
- Implementing atomicity when publishing integration events through the event bus
- Receiving messages from subscriptions: event handlers in receiver microservices
- Idempotency in update message events
- Deduplicating integration event messages
- Deduplicating message events at the EventHandler level
- Deduplicating messages when using RabbitMQ
- Additional resources
- Testing ASP.NET Core services and web apps
- Implementing unit tests for ASP.NET Core Web APIs
- Implementing integration and functional tests for each microservice
- Implementing service tests on a multi-container application
- Testing in eShopOnContainers
- Implement background tasks in microservices with IHostedService and the BackgroundService class
- Registering hosted services in your WebHost or Host
- The IHostedService interface
- Implementing IHostedService with a custom hosted service class deriving from the BackgroundService base class
- Summary class diagram
- Deployment considerations and takeaways
- Additional resources
- Implement API Gateways with Ocelot
- Architect and design your API Gateways
- Sample microservices/containers to reroute through the API Gateways
- Implementing your API Gateways with Ocelot
- Using a single Docker container image to run multiple different API Gateway / BFF container types
- The Gateway aggregation pattern in eShopOnContainers
- Authentication and authorization in Ocelot API Gateways
- Using Kubernetes Ingress plus Ocelot API Gateways
- Additional cross-cutting features in an Ocelot API Gateway
- Tackle Business Complexity in a Microservice with DDD and CQRS Patterns
- Additional resources
- DDD (Domain-Driven Design)
- DDD books
- DDD training
- Apply simplified CQRS and DDD patterns in a microservice
- Apply CQRS and CQS approaches in a DDD microservice in eShopOnContainers
- CQRS and DDD patterns are not top-level architectures
- Implement reads/queries in a CQRS microservice
- Use ViewModels specifically made for client apps, independent from domain model constraints
- Use Dapper as a micro ORM to perform queries
- Dynamic versus static ViewModels
- ViewModel as dynamic type
- ViewModel as predefined DTO classes
- Describe response types of Web APIs
- Additional resources
- Design a DDD-oriented microservice
- Keep the microservice context boundaries relatively small
- Layers in DDD microservices
- The domain model layer
- The application layer
- The infrastructure layer
- Design a microservice domain model
- The Domain Entity pattern
- Rich domain model versus anemic domain model
- The Value Object pattern
- The Aggregate pattern
- The Aggregate Root or Root Entity pattern
- Implement a microservice domain model with .NET
- Domain model structure in a custom .NET Standard Library
- Structure aggregates in a custom .NET Standard library
- Implement domain entities as POCO classes
- Encapsulate data in the Domain Entities
- Map properties with only get accessors to the fields in the database table
- Map fields without properties
- Additional resources
- Seedwork (reusable base classes and interfaces for your domain model)
- The custom Entity base class
- Repository contracts (interfaces) in the domain model layer
- Additional resources
- Implement value objects
- Important characteristics of value objects
- Value object implementation in C#
- Value object comparison semantics
- How to persist value objects in the database with EF Core 2.0 and later
- Background and older approaches using EF Core 1.1
- Persist value objects as owned entity types in EF Core 2.0 and later
- Additional details on owned entity types
- Owned entities capabilities
- Owned entities limitations
- Main differences with EF6’s complex types
- Additional resources
- Use enumeration classes instead of enum types
- Implement an Enumeration base class
- Additional resources
- Design validations in the domain model layer
- Implement validations in the domain model layer
- Validate conditions and throw exceptions
- Use validation attributes in the model based on data annotations
- Validate entities by implementing the Specification pattern and the Notification pattern
- Use deferred validation in the domain
- Two-step validation
- Additional resources
- Client-side validation (validation in the presentation layers)
- Additional resources
- Validation in Xamarin mobile apps
- Validation in ASP.NET Core apps
- Validation in SPA Web apps (Angular 2, TypeScript, JavaScript, Blazor WebAssembly)
- Domain events: Design and implementation
- What is a domain event?
- Domain events versus integration events
- Domain events as a preferred way to trigger side effects across multiple aggregates within the same domain
- Implement domain events
- Raise domain events
- The deferred approach to raise and dispatch events
- Single transaction across aggregates versus eventual consistency across aggregates
- The domain event dispatcher: mapping from events to event handlers
- How to subscribe to domain events
- How to handle domain events
- Domain events can generate integration events to be published outside of the microservice boundaries
- Conclusions on domain events
- Additional resources
- Design the infrastructure persistence layer
- The Repository pattern
- Define one repository per aggregate
- Enforce one aggregate root per repository
- The Repository pattern makes it easier to test your application logic
- The difference between the Repository pattern and the legacy Data Access class (DAL class) pattern
- Implementing Unit of Work
- Repositories shouldn’t be mandatory
- Additional resources
- Repository pattern
- Unit of Work pattern
- Implement the infrastructure persistence layer with Entity Framework Core
- Introduction to Entity Framework Core
- Infrastructure in Entity Framework Core from a DDD perspective
- Implement custom repositories with Entity Framework Core
- Methods to implement in a repository (updates or transactions versus queries)
- Using a custom repository versus using EF DbContext directly
- EF DbContext and IUnitOfWork instance lifetime in your IoC container
- The repository instance lifetime in your IoC container
- Table mapping
- Data Annotations versus Fluent API
- Fluent API and the OnModelCreating method
- The Hi/Lo algorithm in EF Core
- Map fields instead of properties
- Use shadow properties in EF Core, hidden at the infrastructure level
- Implement the Query Specification pattern
- Use NoSQL databases as a persistence infrastructure
- Introduction to Azure Cosmos DB and the native Cosmos DB API
- Implement .NET code targeting MongoDB and Azure Cosmos DB
- Use Azure Cosmos DB from .NET containers
- Use MongoDB API for local dev/test Linux/Windows containers plus Azure Cosmos DB
- Analyze your approach for production applications: MongoDB API vs. Cosmos DB API
- The code: Use MongoDB API in .NET applications
- A Model used by MongoDB API
- Retrieve the database and the collection
- Retrieve the data
- Use an env-var in the docker-compose.override.yml file for the MongoDB connection string
- Additional resources
- Design the microservice application layer and Web API
- Use SOLID principles and Dependency Injection
- Implement the microservice application layer using the Web API
- Use Dependency Injection to inject infrastructure objects into your application layer
- Register the dependency implementation types and interfaces or abstractions
- Use the built-in IoC container provided by ASP.NET Core
- Use the Scrutor library for automatic types registration
- Additional resources
- Use Autofac as an IoC container
- Additional resources
- Implement the Command and Command Handler patterns
- The command class
- The Command handler class
- The Command process pipeline: how to trigger a command handler
- Use the Mediator pattern (in-memory) in the command pipeline
- Use message queues (out-of-proc) in the command’s pipeline
- Implement the command process pipeline with a mediator pattern (MediatR)
- Implement idempotent Commands
- Register the types used by MediatR
- Apply cross-cutting concerns when processing commands with the Behaviors in MediatR
- Additional resources
- The mediator pattern
- The decorator pattern
- MediatR (Jimmy Bogard)
- Fluent validation
- Implement resilient applications
- Handle partial failure
- Strategies to handle partial failure
- Implement retries with exponential backoff
- Implement resilient Entity Framework Core SQL connections
- Execution strategies and explicit transactions using BeginTransaction and multiple DbContexts
- Additional resources
- Use IHttpClientFactory to implement resilient HTTP requests
- Issues with the original HttpClient class available in .NET
- Benefits of using IHttpClientFactory
- Multiple ways to use IHttpClientFactory
- How to use Typed Clients with IHttpClientFactory
- HttpClient lifetimes
- Implement your Typed Client classes that use the injected and configured HttpClient
- Use your Typed Client classes
- Additional resources
- Implement HTTP call retries with exponential backoff with IHttpClientFactory and Polly policies
- Add a jitter strategy to the retry policy
- Additional resources
- Implement the Circuit Breaker pattern
- Implement Circuit Breaker pattern with IHttpClientFactory and Polly
- Test Http retries and circuit breakers in eShopOnContainers
- Test the circuit breaker in eShopOnContainers
- Additional resources
- Health monitoring
- Implement health checks in ASP.NET Core services
- Use the HealthChecks feature in your back-end ASP.NET microservices
- HealthChecks implementation in eShopOnContainers
- Query your microservices to report about their health status
- Use watchdogs
- Health checks when using orchestrators
- Advanced monitoring: visualization, analysis, and alerts
- Additional resources
- Make secure .NET Microservices and Web Applications
- Implement authentication in .NET microservices and web applications
- Authenticate with ASP.NET Core Identity
- Authenticate with external providers
- Authenticate with bearer tokens
- Authenticate with an OpenID Connect or OAuth 2.0 Identity provider
- Issue security tokens from an ASP.NET Core service
- Consume security tokens
- Additional resources
- About authorization in .NET microservices and web applications
- Implement role-based authorization
- Implement policy-based authorization
- Authorization and minimal apis
- Additional resources
- Store application secrets safely during development
- Store secrets in environment variables
- Store secrets with the ASP.NET Core Secret Manager
- Use Azure Key Vault to protect secrets at production time
- .NET Microservices Architecture key takeaways
Dostları ilə paylaş: |
|
|