Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel wird gezeigt, wie Sie das Modern Web App-Muster implementieren. Das moderne Web-App-Muster definiert, wie Sie Web-Apps in der Cloud modernisieren und eine dienstorientierte Architektur einführen sollten. Das Modern Web App-Muster bietet präskriptive Architektur, Code und Konfigurationsanleitungen, die den Prinzipien des Azure Well-Architected Framework entsprechen und auf dem zuverlässigen Web App-Muster basieren.
Gründe für die Verwendung des modernen Web-App-Musters
Das Muster "Modern Web App" kann Ihnen dabei helfen, bereiche mit hoher Nachfrage in einer Web-App zu optimieren. Es enthält detaillierte Anleitungen zum Entkoppeln dieser Bereiche, die eine unabhängige Skalierung für die Kostenoptimierung ermöglichen. Mit diesem Ansatz können Sie dedizierte Ressourcen kritischen Komponenten zuordnen, wodurch die Gesamtleistung verbessert wird. Die Entkopplung von separierbaren Diensten kann die Zuverlässigkeit verbessern, indem verhindert wird, dass Verlangsamungen in einem Teil der App andere Teile beeinträchtigen. Durch die Entkoppelung können Sie auch einzelne App-Komponenten unabhängig voneinander versionieren.
Implementieren des modernen Web-App-Musters
Dieser Artikel enthält Architektur-, Code- und Konfigurationsanleitungen für die Implementierung des Modern Web App-Musters. Verwenden Sie die folgenden Links, um zu den benötigten Anleitungen zu wechseln:
- Architekturleitfaden. Erfahren Sie, wie Sie Web-App-Komponenten modularisieren und geeignete Plattform als Dienstlösungen (PaaS) auswählen.
- Codeleitfaden. Implementieren Sie vier Entwurfsmuster, um die entkoppelten Komponenten zu optimieren: Strangler Fig, Queue-Based Lastenausgleich, konkurrierende Verbraucher und Integritätsendpunktüberwachung.
- Konfigurationsleitfaden. Konfigurieren Sie die Authentifizierung, Autorisierung, automatische Skalierung und Containerisierung für die entkoppelten Komponenten.
Tipp
Es gibt eine Referenzimplementierung (Beispiel-App) des modernen Web-App-Musters. Sie stellt den Endzustand der Implementierung der modernen Web-App dar. Es handelt sich um eine Web-App mit Produktionsniveau, die alle in diesem Artikel beschriebenen Code-, Architektur- und Konfigurationsupdates enthält. Stellen Sie die Referenzimplementierung bereit, um die Implementierung des modernen Web-App-Musters anzuleiten.
Anleitung zur Architektur
Das moderne Web-App-Muster basiert auf dem zuverlässigen Web-App-Muster. Für die Implementierung sind einige zusätzliche Architekturkomponenten erforderlich. Sie benötigen eine Nachrichtenwarteschlange, Containerplattform, entkoppelte Dienstdatenspeicher und Containerregistrierung. Das folgende Diagramm veranschaulicht die Basisarchitektur.
Für ein höheres Ziel auf Dienstebene (SLO) können Sie Ihrer Web-App-Architektur eine zweite Region hinzufügen. Wenn Sie eine zweite Region hinzufügen, müssen Sie den Lastenausgleich so konfigurieren, dass der Datenverkehr an diese Region weitergeleitet wird, um entweder eine aktive oder eine passive Konfiguration zu unterstützen. Verwenden Sie eine Hub-and-Spoke-Netzwerktopologie, um Ressourcen wie eine Netzwerkfirewall zu zentralisieren und freizugeben. Greifen Sie über das virtuelle Hubnetzwerk auf das Container-Repository zu. Wenn Sie über virtuelle Computer verfügen, fügen Sie dem virtuellen Hubnetzwerk einen Bastionhost hinzu, um sie mit verbesserter Sicherheit zu verwalten. Das folgende Diagramm veranschaulicht diese Architektur.
Entkoppeln der Architektur
Um das moderne Web-App-Muster zu implementieren, müssen Sie die vorhandene Web-App-Architektur entkoppeln. Die Entkoppelung der Architektur umfasst das Aufteilen einer monolithischen Anwendung in kleinere unabhängige Dienste, die jeweils für ein bestimmtes Feature oder eine bestimmte Funktionalität verantwortlich sind. Dieser Prozess beinhaltet die Auswertung der aktuellen Web-App, das Ändern der Architektur und schließlich das Extrahieren des Web-App-Codes in eine Containerplattform. Ziel ist es, Anwendungsdienste systematisch zu identifizieren und zu extrahieren, die von der entkoppelten Entkoppelung am meisten profitieren. Befolgen Sie die folgenden Empfehlungen, um Ihre Architektur zu entkoppeln:
Identifizieren sie Dienstgrenzen. Wenden Sie domänengesteuerte Designprinzipien an, um gebundene Kontexte innerhalb Ihrer monolithischen Anwendung zu identifizieren. Jeder gebundene Kontext stellt eine logische Grenze dar und kann ein Kandidat für einen separaten Dienst sein. Dienste, die unterschiedliche Geschäftsfunktionen darstellen und weniger Abhängigkeiten aufweisen, sind gute Kandidaten für die Entkoppelung.
Evaluieren Sie die Dienstvorteile. Konzentrieren Sie sich auf Dienste, die am meisten von der unabhängigen Skalierung profitieren. Das Decoupieren dieser Dienste und das Konvertieren von Verarbeitungsaufgaben von synchronen zu asynchronen Vorgängen ermöglicht eine effizientere Ressourcenverwaltung, unterstützt unabhängige Bereitstellungen und reduziert das Risiko, andere Teile der Anwendung während Updates oder Änderungen zu beeinflussen. Sie können z. B. das Bestellchecken von der Auftragsverarbeitung trennen.
Bewerten Sie die technische Machbarkeit. Untersuchen Sie die aktuelle Architektur, um technische Einschränkungen und Abhängigkeiten zu identifizieren, die sich auf den Entkopplungsprozess auswirken können. Planen Sie, wie Daten über Dienste hinweg verwaltet und gemeinsam genutzt werden. Entkoppelte Dienste sollten ihre eigenen Daten verwalten und den direkten Datenbankzugriff über Dienstgrenzen hinweg minimieren.
Stellen Sie Azure-Dienste bereit. Wählen Sie die Azure-Dienste aus, die Sie benötigen, um den Web App-Dienst zu unterstützen, den Sie extrahieren möchten, und stellen Sie sie bereit. Anleitungen finden Sie unter Auswählen der richtigen Azure-Dienste.
Decouple Web App-Dienste. Definieren Sie klare Schnittstellen und APIs, damit die neu extrahierten Webdienste mit anderen Teilen des Systems interagieren können. Entwerfen Sie eine Datenverwaltungsstrategie, mit der jeder Dienst seine eigenen Daten verwalten kann und gleichzeitig Konsistenz und Integrität gewährleistet. Spezifische Implementierungsstrategien und Entwurfsmuster, die während dieses Extraktionsprozesses verwendet werden sollen, finden Sie im Codeleitfaden dieses Artikels.
Verwenden Sie einen unabhängigen Speicher für entkoppelte Dienste. Jeder entkoppelte Dienst sollte über einen eigenen isolierten Datenspeicher verfügen, um eine unabhängige Versionsverwaltung, Bereitstellung und Skalierbarkeit zu ermöglichen und die Datenintegrität aufrechtzuerhalten. Die Referenzimplementierung trennt beispielsweise den Ticketrenderingdienst von der Web-API und beseitigt die Notwendigkeit, dass der Dienst auf die API-Datenbank zugreifen kann. Stattdessen übergibt der Dienst die URL, in der Ticketbilder über eine Azure Service Bus-Nachricht zurück an die Web-API generiert wurden, und die API behält den Pfad zu ihrer Datenbank bei.
Implementieren Sie separate Bereitstellungspipelines für jeden entkoppelten Dienst. Durch separate Bereitstellungspipelines kann jeder Dienst in seinem eigenen Tempo aktualisiert werden. Wenn verschiedene Teams oder Organisationen innerhalb Ihres Unternehmens unterschiedliche Dienste besitzen, gibt eine separate Bereitstellungspipeline jedem Team die Kontrolle über seine eigenen Bereitstellungen. Verwenden Sie fortlaufende Integrations- und Continuous Delivery-Tools (CI/CD), z. B. Jenkins, GitHub-Aktionen oder Azure-Pipelines, um diese Pipelines einzurichten.
Überarbeiten Sie die Sicherheitskontrollen. Stellen Sie sicher, dass Ihre Sicherheitssteuerelemente aktualisiert werden, um die neue Architektur zu berücksichtigen, einschließlich Firewallregeln und Zugriffssteuerungen.
Auswählen der richtigen Azure-Dienste
Konsultieren Sie für jeden Azure-Dienst in Ihrer Architektur die entsprechende Anleitung zum Azure-Dienst im Well-Architected Framework. Für das moderne Web-App-Muster benötigen Sie ein Messaging-System, das asynchrones Messaging unterstützt, eine Anwendungsplattform, die Containerisierung unterstützt, und ein Container-Image-Repository.
Wählen Sie eine Nachrichtenwarteschlange aus. Eine Nachrichtenwarteschlange ist eine wichtige Komponente dienstorientierter Architekturen. Sie entkoppelt Nachrichtensender und Empfänger, um asynchrones Messaging zu aktivieren. Verwenden Sie die Anleitungen zum Auswählen eines Azure-Messagingdiensts, um ein Azure-Messagingsystem auszuwählen, das Ihre Entwurfsanforderungen unterstützt. Azure verfügt über drei Messagingdienste: Azure Event Grid, Azure Event Hubs und Azure Service Bus. Beginnen Sie mit Service Bus als Standardauswahl, und verwenden Sie die anderen beiden Optionen, wenn Service Bus Ihre Anforderungen nicht erfüllt.
Dienst Anwendungsfall Dienstbus Wählen Sie Service Bus für eine zuverlässige, sortierte und möglicherweise transaktionsbezogene Zustellung von hochwertigen Nachrichten in Unternehmensanwendungen aus. Ereignisraster Wählen Sie "Ereignisraster" aus, wenn Sie eine große Anzahl diskreter Ereignisse effizient behandeln müssen. Ereignisraster ist für ereignisgesteuerte Anwendungen skalierbar, bei denen viele kleine unabhängige Ereignisse (z. B. Ressourcenzustandsänderungen) in einem Veröffentlichungsabonnementmodell mit geringer Latenz an Abonnenten weitergeleitet werden müssen. Ereignis-Hubs Wählen Sie Event Hubs für eine massive Datenaufnahme mit hohem Durchsatz aus, z. B. Telemetrie, Protokolle oder Echtzeitanalysen. Event Hubs sind für Streamingszenarien optimiert, in denen Massendaten kontinuierlich aufgenommen und verarbeitet werden müssen. Implementieren Sie einen Containerdienst. Für die Komponenten Ihrer Anwendung, die Sie containerisieren möchten, benötigen Sie eine Anwendungsplattform, die Container unterstützt. Die Anleitung zum Auswählen eines Azure-Containerdiensts kann Ihnen dabei helfen, Ihre Entscheidung zu treffen. Azure verfügt über drei Prinzipalcontainerdienste: Azure Container Apps, Azure Kubernetes Service (AKS) und Azure-App Service. Beginnen Sie mit Container-Apps als Standardauswahl, und verwenden Sie die anderen beiden Optionen, wenn Container-Apps Ihre Anforderungen nicht erfüllen.
Dienst Anwendungsfall Container-Apps Wählen Sie Container-Apps aus, wenn Sie eine serverlose Plattform benötigen, die Container in ereignisgesteuerten Anwendungen automatisch skaliert und verwaltet. AKS Wählen Sie AKS aus, wenn Sie eine detaillierte Kontrolle über Kubernetes-Konfigurationen und erweiterte Features für Skalierung, Netzwerk und Sicherheit benötigen. Web-Apps für Container Wählen Sie Web App für Container in App Service für die einfachste PaaS-Oberfläche aus. Implementieren Sie ein Container-Repository. Wenn Sie einen containerbasierten Computedienst verwenden, müssen Sie über ein Repository verfügen, um die Containerimages zu speichern. Sie können eine öffentliche Containerregistrierung wie Docker Hub oder eine verwaltete Registrierung wie Azure Container Registry verwenden. Die Einführung in Containerregistrierungen in Azure kann Ihnen dabei helfen, Ihre Entscheidung zu treffen.
Anleitung zum Code
Um einen unabhängigen Dienst erfolgreich zu entkoppeln und zu extrahieren, müssen Sie Ihren Web-App-Code mit den folgenden Entwurfsmustern aktualisieren: Strangler Fig, Warteschlangenbasierter Lastenabgleich, Konkurrierende Verbraucher, Überwachung der Integrität von Endpunkten und das Wiederholungsmuster. Die Rollen dieser Muster werden hier veranschaulicht:
Strangler Fig-Muster: Das Strangler Fig-Muster migriert Funktionen inkrementell von einer monolithischen Anwendung zum entkoppelten Dienst. Implementieren Sie dieses Muster in der Hauptweb-App, um die Funktionalität schrittweise auf unabhängige Dienste zu migrieren, indem Sie den Datenverkehr basierend auf Endpunkten leiten.
Warteschlangenbasiertes Lastenausgleichsmuster: Das Muster für das warteschlangenbasierte Lastenausgleich verwaltet den Nachrichtenfluss zwischen dem Produzenten und dem Consumer mithilfe einer Warteschlange als Puffer. Implementieren Sie dieses Muster in der Codebasis, die Nachrichten für die Warteschlange generiert. Der entkoppelte Dienst verwendet diese Nachrichten dann asynchron aus der Warteschlange.
Konkurrierende Verbraucher: Das Muster konkurrierender Verbraucher ermöglicht es mehreren Instanzen des entkoppelten Dienstes, unabhängig voneinander aus derselben Nachrichtenwarteschlange zu lesen und um die Verarbeitung von Nachrichten zu konkurrieren. Implementieren Sie dieses Muster im entkoppelten Dienst, um Aufgaben über mehrere Instanzen hinweg zu verteilen.
Überwachung der Integrität von Endpunkten: Das Muster der Überwachung der Integrität von Endpunkten macht Endpunkte zur Überwachung des Status und der Integrität verschiedener Teile der Web-App verfügbar. (4a) Implementieren Sie dieses Muster in der Hauptweb-App. (4b) Implementieren Sie sie auch im entkoppelten Dienst, um den Status von Endpunkten nachzuverfolgen.
Wiederholungsmuster: Das Wiederholungsmuster behandelt vorübergehende Fehler durch Wiederholungsvorgänge, die zeitweise fehlschlagen können. (5a) Implementieren Sie dieses Muster für alle ausgehenden Anrufe an andere Azure-Dienste in der Hauptweb-App, z. B. Anrufe an die Nachrichtenwarteschlange und private Endpunkte. (5b) Implementieren Sie dieses Muster auch im entkoppelten Dienst, um vorübergehende Fehler bei Aufrufen an die privaten Endpunkte zu behandeln.
Jedes Entwurfsmuster bietet Vorteile, die mit einer oder mehreren Säulen des Well-Architected Frameworks übereinstimmen. Details finden Sie in der folgenden Tabelle.
| Entwurfsmuster | Implementierungsspeicherort | Zuverlässigkeit (Reliability, RE) | Sicherheit (Security, SE) | Kostenoptimierung (Cost Optimization, CO) | Erstklassige Betriebsprozesse (Operational Excellence, OE) | Leistungseffizienz (Performance Efficiency, PE) | Unterstützung von Grundsätzen des well-Architected Framework |
|---|---|---|---|---|---|---|---|
| Strangler-Muster | Hauptweb-App | ✔ | ✔ | ✔ |
RE:08 CO:07 CO:08 OE:06 OE:11 |
||
| Muster „Warteschlangenbasierter Lastenausgleich“ | Hauptweb-App (Nachrichtenproduzent) | ✔ | ✔ | ✔ |
RE:07 RE:07 CO:12 PE:05 |
||
| Muster mit konkurrierenden Consumern | Entkoppelter Dienst | ✔ | ✔ | ✔ |
RE:05 RE:07 CO:05 CO:07 PE:05 PE:07 |
||
| Integritätsendpunktüberwachungsmuster | Hauptweb-App und entkoppelter Dienst | ✔ | ✔ | ✔ |
RE:07 RE:10 OE:07 PE:05 |
||
| Wiederholungsmuster | Hauptweb-App und entkoppelter Dienst | ✔ | RE:07 |
Implementieren des Strangler Fig-Musters
Verwenden Sie das Strangler Fig Muster, um die Funktionalität schrittweise von der monolithischen Codebasis zu neuen unabhängigen Diensten zu migrieren. Extrahieren Sie die neuen Dienste aus der vorhandenen monolithischen Codebasis, und modernisieren Sie langsam kritische Teile der Web-App. Befolgen Sie die folgenden Empfehlungen, um das Strangler Fig-Muster zu implementieren:
Richten Sie eine Routingebene ein. Implementieren Sie in der monolithischen Web-App-Codebasis eine Routingebene, die datenverkehrsbasiert auf Endpunkten leitet. Verwenden Sie die benutzerdefinierte Routinglogik nach Bedarf, um bestimmte Geschäftsregeln für das Weiterleiten von Datenverkehr zu behandeln. Wenn Sie beispielsweise einen
/usersEndpunkt in Ihrer monolithischen App haben und diese Funktionalität in den entkoppelten Dienst verschieben, leitet die Routingebene alle Anforderungen an/usersan den neuen Dienst weiter.Verwalten Sie den Featurerollout. Verwenden Sie .NET-Featureverwaltungsbibliotheken, um Featurekennzeichen und mehrstufiges Rollout zu implementieren, um die entkoppelten Dienste schrittweise einzuführen. Das vorhandene monolithische App-Routing sollte steuern, wie viele Anforderungen die entkoppelten Dienste empfangen. Beginnen Sie mit einem kleinen Prozentsatz der Anforderungen und erhöhen Sie die Nutzung im Laufe der Zeit, wenn Sie Vertrauen in die Stabilität und Leistung des neuen Diensts erhalten. Die Referenzimplementierung extrahiert beispielsweise die Ticketrenderingfunktion in einen eigenständigen Dienst, der schrittweise eingeführt werden kann, um einen größeren Teil der Ticketrenderinganforderungen zu verarbeiten. Da der neue Dienst seine Zuverlässigkeit und Leistung beweist, kann er schließlich die gesamte Ticketrendering-Funktionalität vom Monolithen übernehmen und den Übergang abschließen.
Verwenden Sie bei Bedarf einen Fassadenservice. Ein Fassadendienst ist nützlich, wenn eine einzelne Anforderung mit mehreren Diensten interagieren muss, oder wenn Sie die Komplexität des zugrunde liegenden Systems vom Client ausblenden möchten. Wenn der entkoppelte Dienst jedoch keine öffentlich zugänglichen APIs enthält, ist möglicherweise kein Fassadendienst erforderlich. Implementieren Sie in der monolithischen Web-App-Codebasis einen Fassadendienst, um Anforderungen an das entsprechende Back-End (Monolith oder Microservice) weiterzuleiten. Stellen Sie im neuen entkoppelten Dienst sicher, dass der neue Dienst Anforderungen unabhängig verarbeiten kann, wenn über die Fassade zugegriffen wird.
Implementieren des Muster für den wartenschlangenbasierten Lastenausgleich
Implementieren Sie das Warteschlangenbasierte Lastenausgleichsmuster auf dem Produzententeil des entkoppelten Diensts, um Aufgaben asynchron zu verarbeiten, die keine sofortigen Antworten benötigen. Dieses Muster verbessert die Reaktionsfähigkeit und Skalierbarkeit des gesamten Systems, indem eine Warteschlange zum Verwalten der Workloadverteilung verwendet wird. Es ermöglicht dem entkoppelten Dienst das Verarbeiten von Anforderungen mit einer konsistenten Rate. Befolgen Sie die folgenden Empfehlungen, um dieses Muster effektiv zu implementieren:
Verwenden Sie nicht blockierende Nachrichtenwarteschlangen. Stellen Sie sicher, dass der Prozess, der Nachrichten an die Warteschlange sendet, keine anderen Prozesse blockiert, während er darauf wartet, dass der entkoppelte Dienst die Nachrichten in der Warteschlange verarbeitet. Wenn der Prozess das Ergebnis des entkoppelten Servicevorgangs erfordert, sollten Sie eine alternative Möglichkeit haben, die Situation zu bewältigen, während Sie auf den Abschluss des in der Warteschlange befindlichen Vorgangs warten. Die Referenzimplementierung verwendet z. B. Service Bus und das
awaitSchlüsselwort zummessageSender.PublishAsync()asynchronen Veröffentlichen von Nachrichten in der Warteschlange, ohne den Thread zu blockieren, der diesen Code ausführt:// Asynchronously publish a message without blocking the calling thread. await messageSender.PublishAsync(new TicketRenderRequestMessage(Guid.NewGuid(), ticket, null, DateTime.Now), CancellationToken.None);Mit diesem Ansatz wird sichergestellt, dass die Hauptanwendung reaktionsfähig bleibt und gleichzeitig andere Aufgaben ausführen kann, während der entkoppelte Dienst die in die Warteschlange gestellten Anforderungen mit überschaubarer Geschwindigkeit verarbeitet.
Implementieren Sie den Wiederholungs- und Entfernungsvorgang für Nachrichten. Implementieren Sie einen Mechanismus zum Wiederholen der Verarbeitung von Nachrichten in die Warteschlange, die nicht erfolgreich verarbeitet werden können. Wenn Fehler weiterhin bestehen, sollten diese Nachrichten aus der Warteschlange entfernt werden. Beispielsweise verfügt Service Bus über integrierte Funktionen für wiederholungs- und inaktive Warteschlangen.
Konfigurieren Sie die idempotente Nachrichtenverarbeitung. Die Logik, die Nachrichten aus der Warteschlange verarbeitet, muss idempotent sein, um Fälle zu behandeln, in denen eine Nachricht möglicherweise mehrmals verarbeitet wird. Die Referenzimplementierung verwendet
ServiceBusClient.CreateProcessorz. B. undAutoCompleteMessages = trueReceiveMode = ServiceBusReceiveMode.PeekLockstellt sicher, dass Nachrichten nur einmal verarbeitet werden und bei Fehlern erneut verarbeitet werden können. Der folgende Code veranschaulicht diese Logik.// Create a processor for idempotent message processing. var processor = serviceBusClient.CreateProcessor(path, new ServiceBusProcessorOptions { // Allow the messages to be auto-completed // if processing finishes without failure. AutoCompleteMessages = true, // PeekLock mode provides reliability in that unsettled messages // will be redelivered on failure. ReceiveMode = ServiceBusReceiveMode.PeekLock, // Containerized processors can scale at the container level // and need not scale via the processor options. MaxConcurrentCalls = 1, PrefetchCount = 0 });Verwalten Sie Änderungen an der Oberfläche. Die asynchrone Verarbeitung kann dazu führen, dass Aufgaben nicht sofort abgeschlossen werden. Benutzer sollten darauf hingewiesen werden, wenn ihre Aufgabe noch bearbeitet wird, um falsche Erwartungen zu vermeiden und Verwirrung zu vermeiden. Verwenden Sie visuelle Hinweise oder Meldungen, um hinzuweisen, dass eine Aufgabe ausgeführt wird. Geben Sie Benutzern die Möglichkeit, Benachrichtigungen zu erhalten, wenn ihre Aufgabe abgeschlossen ist, z. B. in Form einer E-Mail oder Pushbenachrichtigung.
Implementieren des Musters „Konkurrierende Verbraucher“
Implementieren Sie das Muster Konkurrierende Verbraucher in den entkoppelten Diensten, um eingehende Aufgaben aus der Nachrichtenwarteschlange zu verwalten. Dieses Muster umfasst die Verteilung von Aufgaben über mehrere Instanzen entkoppelter Dienste. Diese Dienste verarbeiten Nachrichten aus der Warteschlange, verbessern den Lastenausgleich und erhöhen die Kapazität des Systems zur Behandlung gleichzeitiger Anforderungen. Das Muster „Konkurrierende Verbraucher“ ist wirksam, wenn:
- Die Abfolge der Nachrichtenverarbeitung ist nicht entscheidend.
- Die Warteschlange bleibt von nicht wohlgeformten Nachrichten unberührt.
- Der Verarbeitungsvorgang ist idempotent, d. h. er kann mehrmals angewendet werden, ohne das Ergebnis über die ursprüngliche Anwendung hinaus zu ändern.
Befolgen Sie die folgenden Empfehlungen, um das Muster konkurrierender Verbraucher zu implementieren:
Verarbeiten Sie gleichzeitig eingehende Nachrichten. Wenn Ihr System Nachrichten aus einer Warteschlange empfängt, stellen Sie sicher, dass das System so konzipiert ist, dass mehrere Nachrichten gleichzeitig verarbeitet werden. Setzen Sie die maximale Anzahl gleichzeitiger Aufrufe auf 1, damit jede Nachricht von einem separaten Verbraucher bearbeitet wird.
Deaktivieren Sie das Vorabrufen. Deaktivieren Sie das Vorabfetchen von Nachrichten, damit Verbraucher Nachrichten nur abrufen, wenn sie bereit sind.
Verwenden Sie zuverlässige Nachrichtenverarbeitungsmodi. Verwenden Sie einen zuverlässigen Verarbeitungsmodus, z. B. PeekLock (oder seine Entsprechung), mit dem Nachrichten, die bei der Verarbeitung fehlschlagen, automatisch erneut angezeigt werden. Dieser Modus bietet mehr Zuverlässigkeit als Löschmethoden. Wenn ein Worker eine Nachricht nicht verarbeiten kann, muss ein anderer in der Lage sein, sie ohne Fehler zu verarbeiten, auch wenn die Nachricht mehrmals bearbeitet wird.
Implementieren Sie die Fehlerbehandlung. Leiten Sie falsch formatierte oder nicht verarbeitete Nachrichten an eine separate Warteschlange mit inaktiven Buchstaben weiter. Dieses Design verhindert die wiederholte Verarbeitung. Sie können beispielsweise Ausnahmen während der Nachrichtenverarbeitung abfangen und die problematische Nachricht in die separate Warteschlange verschieben.
Bearbeiten Sie nicht ordnungsgemäße Nachrichten. Entwerfen Sie Verbraucher so, dass sie die Nachrichten auch dann verarbeiten, wenn diese nicht in der richtigen Reihenfolge ankommen. Wenn Sie über mehrere parallele Consumer verfügen, verarbeiten sie möglicherweise Nachrichten außerhalb der Reihenfolge.
Skalieren Sie basierend auf der Warteschlangenlänge. Dienste, die Nachrichten aus einer Warteschlange verwenden, sollten die automatische Skalierung basierend auf der Warteschlangenlänge oder die Verwendung zusätzlicher Skalierungskriterien in Betracht ziehen, um Spitzen eingehender Nachrichten zu verarbeiten.
Verwenden Sie eine Nachrichtenantwortwarteschlange. Wenn das System Benachrichtigungen für die Verarbeitung nach der Nachricht benötigt, richten Sie eine dedizierte Antwort- oder Antwortwarteschlange ein. Mit diesem Setup wird das Operative Messaging von Benachrichtigungsprozessen getrennt.
Verwenden Sie zustandslose Dienste. Erwägen Sie die Verwendung zustandsloser Dienste zum Verarbeiten von Anforderungen aus einer Warteschlange. Diese Dienste ermöglichen eine einfache Skalierung und effiziente Ressourcennutzung.
Konfigurieren Sie die Protokollierung. Integration der Protokollierung und spezifischer Ausnahmebehandlung im Nachrichtenverarbeitungsworkflow. Konzentrieren Sie sich auf die Erfassung von Serialisierungsfehlern und das Weiterleiten dieser problematischen Nachrichten auf einen Mechanismus mit Einem Totbuchstaben. Diese Protokolle bieten wertvolle Erkenntnisse für die Problembehandlung.
Die Referenzimplementierung verwendet beispielsweise das Muster "Konkurrierende Verbraucher" für einen zustandslosen Dienst, der in Container-Apps ausgeführt wird, um Ticketrenderinganforderungen aus einer ServiceBus-Warteschlange zu verarbeiten. Dieser konfiguriert einen Warteschlangenprozessor mit:
-
AutoCompleteMessages. Schließt Nachrichten automatisch ab, wenn sie ohne Fehler verarbeitet werden. -
ReceiveMode. Verwendet den PeekLock-Modus und Redelivers-Nachrichten, wenn sie nicht festgelegt sind. -
MaxConcurrentCalls. Auf 1 festgelegt, um jeweils eine Nachricht zu behandeln. -
PrefetchCount. Auf 0 festgelegt, um das Vorabrufen von Nachrichten zu vermeiden.
Der Prozessor protokolliert Details zur Nachrichtenverarbeitung, die bei der Problembehandlung und Überwachung hilfreich sein können. Es erfasst Deserialisierungsfehler und leitet ungültige Nachrichten an eine Warteschlange mit inaktiven Buchstaben weiter, um die wiederholte Verarbeitung fehlerhafter Nachrichten zu verhindern. Der Dienst wird auf Containerebene skaliert, wodurch die effiziente Behandlung von Nachrichtenspitzen basierend auf der Warteschlangenlänge ermöglicht wird.
// Create a processor for the given queue that will process
// incoming messages.
var processor = serviceBusClient.CreateProcessor(path, new ServiceBusProcessorOptions
{
// Allow the messages to be auto-completed
// if processing finishes without failure.
AutoCompleteMessages = true,
// PeekLock mode provides reliability in that unsettled messages
// are redelivered on failure.
ReceiveMode = ServiceBusReceiveMode.PeekLock,
// Containerized processors can scale at the container level
// and need not scale via the processor options.
MaxConcurrentCalls = 1,
PrefetchCount = 0
});
// Called for each message received by the processor.
processor.ProcessMessageAsync += async args =>
{
logger.LogInformation("Processing message {MessageId} from {ServiceBusNamespace}/{Path}", args.Message.MessageId, args.FullyQualifiedNamespace, args.EntityPath);
// Unhandled exceptions in the handler will be caught by
// the processor and result in abandoning and dead-lettering the message.
try
{
var message = args.Message.Body.ToObjectFromJson<T>();
await messageHandler(message, args.CancellationToken);
logger.LogInformation("Successfully processed message {MessageId} from {ServiceBusNamespace}/{Path}",args.Message.MessageId, args.FullyQualifiedNamespace, args.EntityPath);
}
catch (JsonException)
{
logger.LogError("Invalid message body; could not be deserialized to {Type}", typeof(T));
await args.DeadLetterMessageAsync(args.Message, $"Invalid message body; could not be deserialized to {typeof(T)}",cancellationToken: args.CancellationToken);
}
};
Implementieren des Musters für Überwachung der Integrität von Endpunkten
Implementieren Sie das Muster für Überwachung der Integrität von Endpunkten im Haupt-App-Code und dem entkoppelten Dienstcode, um den Status von Anwendungsendpunkten nachzuverfolgen. Orchestratoren wie AKS oder Container-Apps können diese Endpunkte abfragen, um den Dienststatus zu überprüfen und fehlerhafte Instanzen neu zu starten. ASP.NET Core-Apps können Middleware für die dedizierte Integritätsprüfung hinzufügen, um Endpunktintegritätsdaten und wichtige Abhängigkeiten effizient zu bedienen. Befolgen Sie die folgenden Empfehlungen, um das Muster für Überwachung der Integrität von Endpunkten zu implementieren:
Implementieren Sie die Integritätsprüfungen. Verwenden Sie ASP.NET Core-Middleware für die Integritätsprüfung, um Endpunkte für die Integritätsprüfung bereitzustellen.
Überprüfen Sie Abhängigkeiten. Stellen Sie sicher, dass die Integritätsprüfungen die Verfügbarkeit wichtiger Abhängigkeiten überprüfen, z. B. die Datenbank, den Speicher und das Messagingsystem. Das Nicht-Microsoft-Paket AspNetCore.Diagnostics.HealthChecks kann Abhängigkeitsprüfungen für viele gängige App-Abhängigkeiten implementieren.
Die Referenzimplementierung verwendet z. B. ASP.NET Core Health Check Middleware, um Endpunkte zur Integritätsprüfung verfügbar zu machen. Es verwendet die
AddHealthChecks()Methode für dasbuilder.ServicesObjekt. Der Code überprüft die Verfügbarkeit von Schlüsselabhängigkeiten, Azure Blob Storage und der Service Bus-Warteschlange mithilfe derAddAzureBlobStorage()Methoden undAddAzureServiceBusQueue()Methoden, die Teil desAspNetCore.Diagnostics.HealthChecksPakets sind. Container-Apps ermöglichen die Konfiguration von Integritätssonden , die überwacht werden, um zu messen, ob Apps fehlerfrei oder recyclingbedürftigend sind.// Add health checks, including health checks for Azure services // that are used by this service. // The Blob Storage and Service Bus health checks are provided by // AspNetCore.Diagnostics.HealthChecks // (a popular open source project) rather than by Microsoft. // https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks builder.Services.AddHealthChecks() .AddAzureBlobStorage(options => { // AddAzureBlobStorage will use the BlobServiceClient registered in DI. // We just need to specify the container name. options.ContainerName = builder.Configuration.GetRequiredConfigurationValue("App:StorageAccount:Container"); }) .AddAzureServiceBusQueue( builder.Configuration.GetRequiredConfigurationValue("App:ServiceBus:Host"), builder.Configuration.GetRequiredConfigurationValue("App:ServiceBus:RenderRequestQueueName"), azureCredentials); // Further app configuration omitted for brevity. app.MapHealthChecks("/health");Konfigurieren Sie Azure-Ressourcen. Konfigurieren Sie die Azure-Ressourcen, um die Integritätsprüfungs-URLs der App zu verwenden, um die Liveität und Bereitschaft zu bestätigen. Beispielsweise verwendet die Referenzimplementierung Bicep, um die Integritätsprüfungs-URLs zu konfigurieren, um die Aktivität und Bereitschaft der Azure-Ressource zu bestätigen. Eine Livenesssonde trifft den
/healthEndpunkt alle 10 Sekunden nach einer anfänglichen Verzögerung von 2 Sekunden.probes: [ { type: 'liveness' httpGet: { path: '/health' port: 8080 } initialDelaySeconds: 2 periodSeconds: 10 } ]
Implementieren des Wiederholungsmusters
Das Wiederholungsmuster ermöglicht es Anwendungen, sich von vorübergehenden Fehlern zu erholen. Das Wiederholungsmuster ist für das zuverlässige Web-App-Muster zentral, sodass Ihre Web-App bereits das Wiederholungsmuster verwenden sollte. Wenden Sie das Wiederholungsmuster auf Anforderungen an die Messagingsysteme und Anforderungen an, die von den entkoppelten Diensten ausgegeben werden, die Sie aus der Web-App extrahieren. Befolgen Sie die folgenden Empfehlungen, um das Wiederholungsmuster zu implementieren:
Konfigurieren Sie Wiederholungsoptionen. Achten Sie bei der Integration in eine Nachrichtenwarteschlange darauf, den Client zu konfigurieren, der für Interaktionen mit der Warteschlange mit den entsprechenden Wiederholungseinstellungen verantwortlich ist. Geben Sie Parameter wie die maximale Anzahl von Wiederholungen, Verzögerung zwischen Wiederholungen und maximale Verzögerung an.
Verwenden Sie das exponentielle Backoff. Implementieren Sie eine exponentielle Backoffstrategie für Wiederholungsversuche. Bei dieser Strategie wird die Zeit zwischen jedem Wiederholungsvorgang exponentiell erhöht, was dazu beiträgt, die Auslastung des Systems in Zeiten hoher Fehlerraten zu verringern.
Verwenden Sie die SDK-Wiederholungsfunktionalität. Verwenden Sie für Dienste mit spezialisierten SDKs wie Service Bus oder Blob Storage die integrierten Wiederholungsmechanismen. Die integrierten Wiederholungsmechanismen sind für die typischen Anwendungsfälle des Diensts optimiert und können Wiederholungsversuche effektiver verarbeiten, wobei weniger Konfiguration erforderlich ist. Die Referenzimplementierung verwendet z. B. die integrierte Wiederholungsfunktionalität des Service Bus SDK (
ServiceBusClientundServiceBusRetryOptions). DasServiceBusRetryOptionsObjekt ruft Einstellungen abMessageBusOptions, um Wiederholungseinstellungen wieMaxRetries,Delay, ,MaxDelayundTryTimeout.// ServiceBusClient is thread-safe and can be reused for the lifetime // of the application. services.AddSingleton(sp => { var options = sp.GetRequiredService<IOptions<MessageBusOptions>>().Value; var clientOptions = new ServiceBusClientOptions { RetryOptions = new ServiceBusRetryOptions { Mode = ServiceBusRetryMode.Exponential, MaxRetries = options.MaxRetries, Delay = TimeSpan.FromSeconds(options.BaseDelaySecondsBetweenRetries), MaxDelay = TimeSpan.FromSeconds(options.MaxDelaySeconds), TryTimeout = TimeSpan.FromSeconds(options.TryTimeoutSeconds) } }; return new ServiceBusClient(options.Host, azureCredential ?? new DefaultAzureCredential(), clientOptions); });Übernehmen Sie Standardresilienzbibliotheken für HTTP-Clients. Integrieren Sie für die HTTP-Kommunikation eine Standardresilienzbibliothek wie Polly oder
Microsoft.Extensions.Http.Resilience. Diese Bibliotheken bieten umfassende Wiederholungsmechanismen, die für die Verwaltung der Kommunikation mit externen Webdiensten von entscheidender Bedeutung sind.Behandeln Sie die Nachrichtensperre. Implementieren Sie für nachrichtenbasierte Systeme Strategien zur Nachrichtenverarbeitung, die Wiederholungsversuche ohne Datenverlust unterstützen, z. B. mithilfe von "Peek-Lock"-Modi, sofern verfügbar. Stellen Sie sicher, dass fehlgeschlagene Nachrichten effektiv wiederholt und nach wiederholten Fehlern in eine Warteschleife verschoben werden.
Implementieren der verteilten Ablaufverfolgung
Da Anwendungen dienstorientiert werden und ihre Komponenten entkoppelt sind, ist die Überwachung des Ausführungsflusses zwischen den Diensten von entscheidender Bedeutung. Das Modern Web App-Muster verwendet Application Insights und Azure Monitor für die Sichtbarkeit der Anwendungsintegrität und -leistung über OpenTelemetry-APIs, die die verteilte Ablaufverfolgung unterstützen.
Die verteilte Ablaufverfolgung verfolgt eine Benutzeranforderung, während sie mehrere Dienste durchläuft. Wenn eine Anforderung empfangen wird, wird sie mit einem Ablaufverfolgungsbezeichner gekennzeichnet, der über HTTP-Header an andere Komponenten übergeben wird, und service bus-Eigenschaften während des Aufrufs von Abhängigkeiten. Ablaufverfolgungen und Protokolle enthalten dann sowohl den Ablaufverfolgungsbezeichner als auch einen Aktivitätsbezeichner (oder einen Span-Bezeichner), der der spezifischen Komponente und der übergeordneten Aktivität entspricht. Überwachungstools wie Application Insights verwenden diese Informationen, um eine Struktur von Aktivitäten und Protokollen über verschiedene Dienste hinweg anzuzeigen, was für die Überwachung verteilter Anwendungen von entscheidender Bedeutung ist.
Installieren Sie OpenTelemetry-Bibliotheken. Verwenden Sie Instrumentationsbibliotheken, um die Ablaufverfolgung und Metriken aus allgemeinen Komponenten zu aktivieren. Fügen Sie bei Bedarf benutzerdefinierte Instrumentierung mit
System.Diagnostics.ActivitySourceSystem.Diagnostics.Activityhinzu. Verwenden Sie Exporterbibliotheken, um die OpenTelemetry-Diagnose zu überwachen und sie in beständigen Speicher aufzuzeichnen. Verwenden Sie vorhandene Exporteure, oder erstellen Sie ihre eigenen mithilfe vonSystem.Diagnostics.ActivityListener.Richten Sie OpenTelemetry ein. Verwenden Sie die Azure Monitor-Verteilung von OpenTelemetry (
Azure.Monitor.OpenTelemetry.AspNetCore). Stellen Sie sicher, dass die Diagnose in Application Insights exportiert wird und integrierte Instrumentierung für allgemeine Metriken, Ablaufverfolgungen, Protokolle und Ausnahmen von der .NET-Runtime und ASP.NET Core enthält. Schließen Sie weitere OpenTelemetry-Instrumentierungspakete für SQL-, Redis- und Azure SDK-Clients ein.Überwachung und Analyse Stellen Sie nach der Konfiguration der Ablaufverfolgung sicher, dass Protokolle, Ablaufverfolgungen, Metriken und Ausnahmen erfasst und an Application Insights gesendet werden. Überprüfen Sie, ob Ablaufverfolgungs-, Aktivitäts- und übergeordnete Aktivitäts-IDs enthalten sind. Mit diesen Bezeichnern können Application Insights die Sichtbarkeit der End-to-End-Ablaufverfolgung über HTTP- und Servicebusgrenzen hinweg bereitstellen. Verwenden Sie dieses Setup, um die Aktivitäten Ihrer Anwendung über Dienste hinweg zu überwachen und zu analysieren.
Im Beispiel der modernen Web-App wird die Azure Monitor-Verteilung von OpenTelemetry (Azure.Monitor.OpenTelemetry.AspNetCore) verwendet. Weitere Instrumentierungspakete werden für SQL-, Redis- und Azure SDK-Clients verwendet. OpenTelemetry ist im Modern Web App-Beispiel-Ticketrenderingdienst wie folgt konfiguriert:
builder.Logging.AddOpenTelemetry(o =>
{
o.IncludeFormattedMessage = true;
o.IncludeScopes = true;
});
builder.Services.AddOpenTelemetry()
.UseAzureMonitor(o => o.ConnectionString = appInsightsConnectionString)
.WithMetrics(metrics =>
{
metrics.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation();
})
.WithTracing(tracing =>
{
tracing.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddSource("Azure.*");
});
Die builder.Logging.AddOpenTelemetry Methode leitet die gesamte Protokollierung über OpenTelemetry weiter, um eine konsistente Ablaufverfolgung und Protokollierung in der gesamten Anwendung sicherzustellen. Da OpenTelemetry-Dienste registriert builder.Services.AddOpenTelemetrysind, wird die Anwendung für das Sammeln und Exportieren von Diagnosen eingerichtet, die dann über UseAzureMonitorApplication Insights an Application Insights gesendet werden. Darüber hinaus wird die Clientinstrumentation für Komponenten wie Service Bus und HTTP-Clients durch WithMetrics und WithTracingkonfiguriert, wodurch automatische Metriken und Ablaufverfolgungssammlungen ohne Änderungen an der vorhandenen Clientverwendung ermöglicht werden. Es ist nur eine Aktualisierung der Konfiguration erforderlich.
Anleitung zur Konfiguration
In den folgenden Abschnitten finden Sie Anleitungen zum Implementieren der Konfigurationsupdates. Jeder Abschnitt richtet sich an einer oder mehreren Säulen des Well-Architected Frameworks aus.
| Konfiguration | Zuverlässigkeit (Reliability, RE) | Sicherheit (Security, SE) | Kostenoptimierung (Cost Optimization, CO) | Erstklassige Betriebsprozesse (Operational Excellence, OE) | Leistungseffizienz (Performance Efficiency, PE) | Unterstützung von Grundsätzen des well-Architected Framework |
|---|---|---|---|---|---|---|
| Konfigurieren der Authentifizierung und Autorisierung | ✔ | ✔ |
SE:05 OE:10 |
|||
| Implementieren der unabhängigen automatischen Skalierung | ✔ | ✔ | ✔ |
RE:06 CO:12 PE:05 |
||
| Containerisieren der Dienstbereitstellung | ✔ | ✔ |
CO:13 PE:09 PE:03 |
Konfigurieren der Authentifizierung und Autorisierung
Befolgen Sie die folgenden Empfehlungen, um die Authentifizierung und Autorisierung für alle neuen Azure-Dienste (Workloadidentitäten) zu konfigurieren, die Sie der Web-App hinzufügen:
Verwenden Sie verwaltete Identitäten für jeden neuen Dienst. Jeder unabhängige Dienst sollte über eine eigene Identität verfügen und verwaltete Identitäten für die Dienst-zu-Dienst-Authentifizierung verwenden. Verwaltete Identitäten machen die Verwaltung von Anmeldeinformationen in Ihrem Code überflüssig und verringern das Risiko von Datenlecks. Sie helfen Ihnen, vertrauliche Informationen wie Verbindungszeichenfolgen in Ihren Code- oder Konfigurationsdateien zu vermeiden.
Gewähren Sie jedem neuen Dienst die geringsten Berechtigungen. Weisen Sie jeder neuen Dienstidentität nur erforderliche Berechtigungen zu. Wenn beispielsweise eine Identität nur an eine Containerregistrierung übertragen werden muss, erteilen Sie ihr keine Pullberechtigungen. Überprüfen Sie diese Berechtigungen regelmäßig, und passen Sie sie bei Bedarf an. Verwenden Sie unterschiedliche Identitäten für unterschiedliche Rollen, z. B. Bereitstellung und die Anwendung. Dies begrenzt den potenziellen Schaden, wenn eine Identität kompromittiert wird.
Verwenden Sie Infrastruktur als Code (Infrastructure as Code, IaC). Verwenden Sie Bicep oder ähnliche IaC-Tools, um Ihre Cloudressourcen zu definieren und zu verwalten. IaC stellt eine konsistente Anwendung von Sicherheitskonfigurationen in Ihren Bereitstellungen sicher und ermöglicht es Ihnen, die Infrastruktureinrichtung zu steuern.
Befolgen Sie die folgenden Empfehlungen, um die Authentifizierung und Autorisierung für Benutzer (Benutzeridentitäten) zu konfigurieren:
Gewähren Sie Benutzern die geringsten Berechtigungen. Stellen Sie wie bei Diensten sicher, dass Benutzern nur die Berechtigungen erteilt werden, die sie zum Ausführen ihrer Aufgaben benötigen. Überprüfen und passen Sie diese Berechtigungen regelmäßig an.
Führen Sie regelmäßige Sicherheitsüberprüfungen durch. Überprüfen Sie regelmäßig Ihre Sicherheitseinrichtung. Suchen Sie nach Fehlkonfigurationen oder unnötigen Berechtigungen, und korrigieren Sie sie sofort.
Die Referenzimplementierung verwendet IaC, um verwaltete Identitäten hinzugefügten Diensten und bestimmten Rollen jeder Identität zuzuweisen. Er definiert Rollen- und Berechtigungszugriff für die Bereitstellung (containerRegistryPushRoleId), anwendungsbesitzer (containerRegistryPushRoleId) und container-Apps-Anwendung (containerRegistryPullRoleId). Das folgende Beispiel veranschaulicht den Code.
roleAssignments: \[
{
principalId: deploymentSettings.principalId
principalType: deploymentSettings.principalType
roleDefinitionIdOrName: containerRegistryPushRoleId
}
{
principalId: ownerManagedIdentity.outputs.principal_id
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: containerRegistryPushRoleId
}
{
principalId: appManagedIdentity.outputs.principal_id
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: containerRegistryPullRoleId
}
\]
Die Referenzimplementierung weist die verwaltete Identität als neue Container-Apps-Identität bei der Bereitstellung zu:
module renderingServiceContainerApp 'br/public:avm/res/app/container-app:0.1.0' = {
name: 'application-rendering-service-container-app'
scope: resourceGroup()
params: {
// Other parameters omitted for brevity.
managedIdentities: {
userAssignedResourceIds: [
managedIdentity.id
]
}
}
}
Konfigurieren der unabhängigen automatischen Skalierung
Das moderne Web-App-Muster beginnt mit dem Aufbrechen der monolithischen Architektur und führt die Dienstentkopplung ein. Wenn Sie eine Web-App-Architektur entkoppeln, können Sie entkoppelte Dienste unabhängig voneinander skalieren. Die Skalierung der Azure-Dienste zur Unterstützung eines unabhängigen Web-App-Dienstes anstelle einer vollständigen Web-App optimiert die Skalierungskosten und erfüllt gleichzeitig die Anforderungen. Befolgen Sie die folgenden Empfehlungen, um Container automatisch zu skalieren:
Verwenden Sie zustandslose Dienste. Stellen Sie sicher, dass Ihre Dienste zustandslos sind. Wenn Ihre .NET-Anwendung den In-Process-Sitzungszustand enthält, externalisieren Sie sie in einen verteilten Cache wie Redis oder eine Datenbank wie SQL Server.
Konfigurieren Sie die Regeln zur automatischen Skalierung. Verwenden Sie die automatischen Skalierungskonfigurationen, die die kostengünstigste Kontrolle über Ihre Dienste bieten. Bei containerisierten Diensten bietet die ereignisbasierte Skalierung, z. B. Kubernetes Event-Driven Autoscaler (KEDA), häufig eine präzise Steuerung, mit der Sie basierend auf Ereignismetriken skalieren können. Container-Apps und AKS unterstützen KEDA. Verwenden Sie für Dienste, die KEDA nicht unterstützen, z. B. App Service, die von der Plattform bereitgestellten features für die automatische Skalierung. Diese Features umfassen häufig die Skalierung, die auf metrikbasierten Regeln oder HTTP-Datenverkehr basiert.
Konfigurieren Sie Mindestreplikate. Um einen Kaltstart zu verhindern, konfigurieren Sie die Einstellungen für die automatische Skalierung, um mindestens ein Replikat beizubehalten. Ein Kaltstart tritt auf, wenn Sie einen Dienst aus einem angehaltenen Zustand initialisieren, wodurch häufig eine verzögerte Antwort entsteht. Wenn das Minimieren von Kosten eine Priorität ist und Sie Verzögerungen beim Kaltstart tolerieren können, legen Sie die mindeste Replikatanzahl auf 0 fest, wenn Sie die automatische Skalierung konfigurieren.
Konfigurieren Sie eine Abkühlzeit. Wenden Sie eine geeigneten Abkühlzeit an, um eine Verzögerung zwischen Skalierungsereignissen einzuführen. Ziel ist es, übermäßige Skalierungsaktivitäten zu verhindern , die durch temporäre Auslastungsspitzen ausgelöst werden.
Konfigurieren Sie die warteschlangenbasierte Skalierung. Wenn Ihre Anwendung eine Nachrichtenwarteschlange wie Service Bus verwendet, konfigurieren Sie Ihre Einstellungen für die automatische Skalierung basierend auf der Länge der Warteschlange mit Anforderungsnachrichten. Der Scaler zielt darauf ab, ein Replikat des Diensts für alle N-Nachrichten in der Warteschlange zu verwalten (aufgerundet).
Die Referenzimplementierung verwendet z. B. den Service Bus KEDA-Scaler , um die Container-App basierend auf der Länge der Warteschlange zu skalieren. Der service-bus-queue-length-rule Dienst wird basierend auf der Länge einer angegebenen Servicebus-Warteschlange skaliert. Der messageCount-Parameter ist auf 10 festgelegt, sodass die Skalierung ein Dienstreplikat für alle 10 Nachrichten in der Warteschlange hat. Die Parameter scaleMaxReplicas und scaleMinReplicas legen die maximale und minimale Anzahl von Replikaten für den Dienst fest. Der queue-connection-string geheime Schlüssel, der die Verbindungszeichenfolge für die ServiceBus-Warteschlange enthält, wird aus Azure Key Vault abgerufen. Dieser geheime Schlüssel wird verwendet, um die Skalierung beim Service Bus zu authentifizieren.
scaleRules: [
{
name: 'service-bus-queue-length-rule'
custom: {
type: 'azure-servicebus'
metadata: {
messageCount: '10'
namespace: renderRequestServiceBusNamespace
queueName: renderRequestServiceBusQueueName
}
auth: [
{
secretRef: 'render-request-queue-connection-string'
triggerParameter: 'connection'
}
]
}
}
]
scaleMaxReplicas: 5
scaleMinReplicas: 0
Containerisieren der Dienstbereitstellung
In einer containerisierten Bereitstellung werden alle abhängigkeiten, die von der App benötigt werden, in einem einfachen Image gekapselt, das zuverlässig für eine vielzahl von Hosts bereitgestellt werden kann. Befolgen Sie die folgenden Empfehlungen, um die Bereitstellung zu containerisieren:
Identifizieren Sie Domänengrenzen. Beginnen Sie, indem Sie die Domänengrenzen in Ihrer monolithischen Anwendung identifizieren. Auf diese Weise können Sie ermitteln, welche Teile der Anwendung in separate Dienste extrahiert werden können.
Erstellen Sie Docker-Images. Wenn Sie Docker-Images für Ihre .NET-Dienste erstellen, verwenden Sie chiselierte Basisimages. Diese Images enthalten nur den minimalen Satz von Paketen, die für die Ausführung von .NET erforderlich sind, wodurch sowohl die Paketgröße als auch der Angriffsfläche minimiert werden.
Verwenden Sie mehrstufige Dockerfiles. Implementieren Sie mehrstufige Dockerfiles, um Buildzeitressourcen vom Laufzeitcontainerimage zu trennen. Die Verwendung dieser Dateiart trägt dazu bei, dass Ihre Produktionsimages klein und sicher bleiben.
Führen Sie die Ausführung als nichtroot-Benutzer aus. Führen Sie Ihre .NET-Container als nichtroot-Benutzer (über benutzername oder UID $APP_UID) aus, um das Prinzip der geringsten Rechte auszurichten. Dadurch werden die potenziellen Auswirkungen eines kompromittierten Containers begrenzt.
Überwachen Sie Port 8080. Wenn Sie Container als nichtroot-Benutzer ausführen, konfigurieren Sie Ihre Anwendung so, dass sie auf Port 8080 lauscht. Dies ist eine allgemeine Konvention für nichtroot-Benutzer.
Kapseln Sie Abhängigkeiten. Stellen Sie sicher, dass alle Abhängigkeiten für die App im Docker-Containerimage gekapselt sind. Mit der Kapselung können Sie die App zuverlässig auf einer vielzahl von Hosts bereitstellen.
Wählen Sie die richtigen Basisimages aus. Das ausgewählte Basisimage hängt von Ihrer Bereitstellungsumgebung ab. Wenn Sie beispielsweise in Container-Apps bereitstellen, müssen Sie Linux-Docker-Images verwenden.
Die Referenzimplementierung verwendet z. B. einen mehrstufigen Buildprozess. Die ersten Phasen kompilieren und erstellen die Anwendung mit einem vollständigen SDK-Image (mcr.microsoft.com/dotnet/sdk:8.0-jammy). Das endgültige Laufzeitimage wird aus dem chiseled-Basisimage erstellt, das das SDK und Buildartefakte ausschließt. Der Dienst wird als Nicht-Root-Benutzer (USER $APP_UID) ausgeführt und macht Port 8080 verfügbar. Die abhängigkeiten, die für den Betrieb der Anwendung erforderlich sind, sind im Docker-Image enthalten, wie durch die Befehle zum Kopieren von Projektdateien und Wiederherstellen von Paketen belegt. Durch die Verwendung linuxbasierter Images (mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled) wird die Kompatibilität mit Container-Apps sichergestellt, für die Linux-Container für die Bereitstellung erforderlich sind.
# Build in a separate stage to avoid copying the SDK into the final image.
FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
# Restore packages.
COPY ["Relecloud.TicketRenderer/Relecloud.TicketRenderer.csproj", "Relecloud.TicketRenderer/"]
COPY ["Relecloud.Messaging/Relecloud.Messaging.csproj", "Relecloud.Messaging/"]
COPY ["Relecloud.Models/Relecloud.Models.csproj", "Relecloud.Models/"]
RUN dotnet restore "./Relecloud.TicketRenderer/Relecloud.TicketRenderer.csproj"
# Build and publish.
COPY . .
WORKDIR "/src/Relecloud.TicketRenderer"
RUN dotnet publish "./Relecloud.TicketRenderer.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
# Chiseled images contain only the minimal set of packages needed for .NET 8.0.
FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled AS final
WORKDIR /app
EXPOSE 8080
# Copy the published app from the build stage.
COPY --from=build /app/publish .
# Run as nonroot user.
USER $APP_UID
ENTRYPOINT ["dotnet", "./Relecloud.TicketRenderer.dll"]
Bereitstellen der Referenzimplementierung
Stellen Sie die Referenzimplementierung des modernen Web-App-Musters für .NET bereit. Es gibt Anweisungen für die Entwicklungs- und Produktionsbereitstellung im Repository. Nachdem Sie die Implementierung bereitgestellt haben, können Sie Entwurfsmuster simulieren und beobachten.
Das folgende Diagramm zeigt die Architektur der Referenzimplementierung:
Laden Sie eine Visio-Datei dieser Architektur herunter.