The reference sample in this repository builds on the previous Reliable Web App Pattern for .NET. Whereas the Reliable Web App Pattern focused on re-platforming an existing web app into Azure App Service with minimal code changes while still realizing benefits of cloud deployment, the Modern Web App Pattern focuses on modernizing the web app to more fully take advantage of cloud-native features and services.
As part of the modernization of the pattern, several changes have been made to the sample source code and the Azure services used. In addition to the changes documented below, the sample has been updated to use the latest version of the .NET SDK (.NET 8) and to use include Docker support in the dev container for building containerized workloads.
- Azure Container Apps - The Modern Web App Pattern reference sample uses Azure Container Apps to host a new ticket rendering service that was separated from the web API as part of applying the strangler fig pattern. Azure Container Apps is a fully managed serverless platform for running containerized apps. The reference sample uses Azure Container Apps because it provides managed container orchestration with support for automatic scale-in and scale-out based on a wide variety of rules using KEDA scalers. This allows the ticket rendering service to automatically scale to zero when there is no work to be done and automatically scale up, as needed, based on the number of messages in the Service Bus queue.
- Azure Container Registry - Because the Modern Web App Pattern reference sample uses Azure Container Apps, it also uses Azure Container Registry to store the container images for the ticket rendering service. Azure Container Registry is a managed, private Docker registry service that stores and manages container images for all types of container deployments. Azure Container Registry supports the reference sample's SLO goals by being highly available thanks to its geo-replication feature.
- Azure Service Bus - The Modern Web App Pattern reference sample uses Azure Service Bus to enable message-based communication between the Relecloud web API and the new ticket rendering service. Using message-based communication allows improved reliability and performance by decoupling the web API from the ticket rendering service. Applying a queue-based load leveling pattern means that neither the web API nor the ticket rendering service will be affected by large numbers of incoming ticket rendering requests. The reference sample uses Azure Service Bus because it provides a fully managed, reliable, and secure messaging service that supports the reference sample's SLO goals.
- Jump box VM SKU - The Jump box VM SKU has been updated from B2ms to D2s v3 to enable building Docker images from the Jump box. When deploying the sample to a production environment, it's necessary to deploy from a VM connected to the production virtual network. For this to work with Docker images, the VM SKU needs to support nested virtualization. The D2s v3 SKU supports nested virtualization, while the B2ms SKU does not.
- Azure App Configuration Feature Manager - While Azure App Configuration was used in the Reliable Web App Pattern, the Modern Web App Pattern additionally uses the feature management capabilities of Azure App Configuration to enable feature flags in the web API. A feature flag is used to toggle using the new standalone ticket rendering service (via requests to Azure Service Bus) instead of rendering tickets in the web API directly. The feature flag is managed in the Azure portal and can be turned on and off without requiring a code change or redeployment of the web API.
- Ticket rendering service - The ticket rendering service has been separated from the web API and is now hosted in a separate project. The ticket rendering service is a .NET 8 worker service that listens to a Service Bus queue for ticket rendering requests. When a request is received, the service renders the ticket and stores it in Azure Blob Storage. The ticket rendering service includes health checks to ensure that it is responsive and can be automatically restarted if it becomes unresponsive. The health checks include validating that Service Bus and Blob Storage dependencies are available using the open source
AspNetCore.Diagnostics.HealthChecks
package. The service is deployed as a Docker container using chiseled Ubuntu based image. Using a chiseled image means that only the dependencies required by ASP.NET Core are included, reducing size and attack surface. - Replacing System.Drawing with SkiaSharp - In the Reliable Web App reference sample, ticket images were generated with the
System.Drawing
namespace. In the Modern Web App reference sample, the ticket rendering service uses theSkiaSharp
package, instead, to render ticket images. The change was made because the ticket rendering service is hosted in Azure Container Apps which only supports Linux-based containers andSystem.Drawing
is only supported on Windows.SkiaSharp
is a cross-platform 2D graphics library for .NET that works on Linux. - Ticket rendering feature flag - The web API now uses the feature management capabilities of Azure App Configuration to enable a feature flag that toggles using the new standalone ticket rendering service (via requests to Azure Service Bus) instead of rendering tickets in the web API directly. The feature flag is managed in the Azure portal and can be turned on and off without requiring a code change or redeployment of the web API. As part of this change, ticket rendering logic was abstracted behind an interface and the web API now uses different implementations of that interface (to either queue a Service Bus message or render a ticket image) depending on the state of the feature flag. In addition to sending rendering requests to the Service Bus queue, the web API also listens to a Service Bus queue for response messages indicating that a ticket has been rendered. When it receives a response message, the web API updates the location of the ticket image in the database.