Freigeben über


Anwendungsdesign von unternehmenskritischen Workloads in Azure

Wenn Sie eine Anwendung entwerfen, sind sowohl funktionale als auch nicht funktionale Anwendungsanforderungen wichtig. In diesem Entwurfsbereich werden Architekturmuster und Skalierungsstrategien beschrieben, die Dazu beitragen können, dass Ihre Anwendung ausfallsicher ist.

Wichtig

Dieser Artikel ist Teil der Mission-Critical Workload-Reihe von Azure Well-Architected Framework. Wenn Sie mit dieser Reihe nicht vertraut sind, empfehlen wir Ihnen, mit "Was ist eine unternehmenskritische Workload?" zu beginnen.

Skalierungseinheitsarchitektur

Alle funktionalen Aspekte einer Lösung müssen in der Lage sein, skalierungsfähig zu sein, um Änderungen der Nachfrage zu erfüllen, idealerweise automatisch als Reaktion auf Last. Es wird empfohlen, eine Skalierungseinheitsarchitektur zu verwenden, um die End-to-End-Skalierbarkeit durch Abteilung zu optimieren und auch den Prozess des Hinzufügens und Entfernens von Kapazität zu standardisieren. Eine Skalierungseinheit ist eine logische Einheit oder Funktion, die unabhängig voneinander skaliert werden kann. Eine Einheit kann aus Codekomponenten, Anwendungshostingplattformen, Bereitstellungsstempeln, die die zugehörigen Komponenten abdecken, und sogar Abonnements zur Unterstützung von Mehrinstanzenanforderungen bestehen.

Wir empfehlen diesen Ansatz, da er die Skalierungsgrenzwerte einzelner Ressourcen und der gesamten Anwendung behandelt. Dies hilft bei komplexen Bereitstellungs- und Updateszenarien, da eine Skalierungseinheit als eine Einheit bereitgestellt werden kann. Außerdem können Sie bestimmte Komponentenversionen in einer Einheit testen und überprüfen, bevor Sie den Benutzerdatenverkehr darauf weiterleiten.

Angenommen, Ihre unternehmenskritische Anwendung ist ein Online-Produktkatalog. Er verfügt über einen Benutzerfluss zur Verarbeitung von Produktkommentaren und Bewertungen. Der Fluss verwendet APIs zum Abrufen und Veröffentlichen von Kommentaren und Bewertungen sowie unterstützenden Komponenten wie einem OAuth-Endpunkt, Datenspeicher und Nachrichtenwarteschlangen. Die zustandslosen API-Endpunkte stellen präzise funktionale Einheiten dar, die sich an Änderungen bei Bedarf anpassen müssen. Die zugrunde liegende Anwendungsplattform muss auch in der Lage sein, entsprechend zu skalieren. Um Leistungsengpässe zu vermeiden, müssen auch die nachgelagerten Komponenten und Abhängigkeiten entsprechend skaliert werden. Sie können entweder unabhängig, als separate Skalierungseinheiten oder als Teil einer einzelnen logischen Einheit skaliert werden.

Beispielmaßstabeinheiten

Die folgende Abbildung zeigt die möglichen Bereiche für Skalierungseinheiten. Die Bereiche reichen von Microservice-Pods bis hin zu Clusterknoten und regionalen Bereitstellungsstempeln.

Diagramm, das mehrere Bereiche für Skalierungseinheiten zeigt.

Überlegungen zum Entwurf

  • Umfang. Der Umfang einer Skalierungseinheit, die Beziehung zwischen Skalierungseinheiten und deren Komponenten sollte gemäß einem Kapazitätsmodell definiert werden. Berücksichtigen Sie nicht funktionale Anforderungen an die Leistung.

  • Skalierungslimits. Azure-Abonnement-Skalierungslimits und -Kontingente können sich auf das Anwendungsdesign, die Technologieauswahl und die Definition von Skalierungseinheiten auswirken. Skalierungseinheiten können Ihnen dabei helfen, die Skalierungsgrenzwerte eines Diensts zu umgehen. Wenn beispielsweise ein AKS-Cluster in einer Einheit nur 1.000 Knoten aufweisen kann, können Sie zwei Einheiten verwenden, um diese Grenze auf 2.000 Knoten zu erhöhen.

  • Last erwartet. Verwenden Sie die Anzahl der Anforderungen für jeden Benutzerfluss, die erwartete Höchstanforderungsrate (Anforderungen pro Sekunde) und tages-/wöchentliche/saisonale Datenverkehrsmuster, um die grundlegenden Skalierungsanforderungen zu informieren. Berücksichtigen Sie auch die erwarteten Wachstumsmuster sowohl für den Datenverkehr als auch für das Datenvolumen.

  • Akzeptable Leistungseinbußen. Ermitteln Sie, ob ein herabgestufter Dienst mit hohen Reaktionszeiten unter Last akzeptabel ist. Wenn Sie die erforderliche Kapazität modellieren, ist die erforderliche Leistung der Lösung unter Last ein wichtiger Faktor.

  • Nicht funktionale Anforderungen. Technische und geschäftliche Szenarien weisen unterschiedliche Überlegungen zur Resilienz, Verfügbarkeit, Latenz, Kapazität und Beobachtbarkeit auf. Analysieren Sie diese Anforderungen im Kontext wichtiger End-to-End-Benutzerflüsse. Sie haben relative Flexibilität bei der Gestaltung, Entscheidungsfindung und Technologieauswahl auf Benutzerflussebene.

Entwurfsempfehlungen

  • Definieren Sie den Umfang einer Skalierungseinheit und die Grenzwerte, die die Skalierung der Einheit auslösen.

  • Stellen Sie sicher, dass alle Anwendungskomponenten unabhängig oder als Teil einer Skalierungseinheit skaliert werden können, die andere verwandte Komponenten enthält.

  • Definieren Sie die Beziehung zwischen Skalierungseinheiten basierend auf einem Kapazitätsmodell und nicht funktionalen Anforderungen.

  • Definieren Sie einen regionalen Bereitstellungsstempel, um die Bereitstellung, Verwaltung und den Betrieb regionaler Anwendungsressourcen in einer heterogenen, aber unabhängigen Skalierungseinheit zu vereinheitlichen. Da sich die Last erhöht, können zusätzliche Stempel innerhalb derselben Azure-Region oder unterschiedlicher Bereitgestellt werden, um die Lösung horizontal zu skalieren.

  • Verwenden Sie ein Azure-Abonnement als Skalierungseinheit, sodass Skalierungsgrenzwerte innerhalb eines einzelnen Abonnements nicht die Skalierbarkeit einschränken. Dieser Ansatz gilt für szenarien mit hoher Skalierung, die ein erhebliches Datenverkehrsvolumen aufweisen.

  • Modell erforderte Kapazität um identifizierte Datenverkehrsmuster, um sicherzustellen, dass genügend Kapazität zu Spitzenzeiten bereitgestellt wird, um Dienstbeeinträchtigungen zu verhindern. Alternativ können Sie die Kapazität während der Spitzenzeiten optimieren.

  • Messen Sie die Zeit, die zum Ausführen von Skalierungs- und Skalierungsvorgängen erforderlich ist, um sicherzustellen, dass die natürlichen Abweichungen im Datenverkehr kein inakzeptables Maß an Dienstbeeinträchtigungen erzeugen. Verfolgen Sie die Dauer des Skalierungsvorgangs als betriebstechnische Metrik.

Hinweis

Stellen Sie bei der Bereitstellung in einer Azure-Zielzone sicher, dass das Abonnement für die Zielzone der Anwendung zugewiesen ist, um eine klare Verwaltungsgrenze bereitzustellen und die Lauten Nachbarn-Antipattern zu vermeiden.

Globale Verteilung

Es ist unmöglich, Fehler in einer stark verteilten Umgebung zu vermeiden. Dieser Abschnitt enthält Strategien, um viele Fehlerszenarien zu mindern. Die Anwendung muss in der Lage sein, regionalen und zonenalen Fehlern standzuhalten. Sie muss in einem aktiven/aktiven Modell bereitgestellt werden, damit die Last auf alle Regionen verteilt wird.

Schauen Sie sich dieses Video an, um einen Überblick über das Planen von Fehlern in unternehmenskritischen Anwendungen und zur Maximierung der Ausfallsicherheit zu erhalten:

Überlegungen zum Entwurf

  • Redundanz: Ihre Anwendung muss in mehreren Regionen bereitgestellt werden. Darüber hinaus wird dringend empfohlen, in einer Region Verfügbarkeitszonen zu verwenden, um Fehlertoleranz auf Rechenzentrumsebene zu ermöglichen. Verfügbarkeitszonen haben einen Latenzperimeter von weniger als 2 Millisekunden zwischen Verfügbarkeitszonen. Bei Workloads, die über Zonen hinweg "chatty" sind, kann diese Latenz eine Leistungseinbuße für die Interzone-Datenübertragung bedeuten.

  • Aktives/aktives Modell. Eine aktive/aktive Bereitstellungsstrategie wird empfohlen, da sie die Verfügbarkeit maximiert und einen höheren verbundbasierten Servicelevelvertrag (SLA) bereitstellt. Es kann jedoch Herausforderungen bei der Datensynchronisierung und Konsistenz für viele Anwendungsszenarien auftreten. Lösen Sie die Herausforderungen auf Einer Datenplattformebene unter Berücksichtigung der Kompromisse bei erhöhten Kosten- und Engineering-Aufwand.

    Eine aktive/aktive Bereitstellung über mehrere Cloudanbieter hinweg ist eine Möglichkeit, die Abhängigkeit von globalen Ressourcen innerhalb eines einzelnen Cloudanbieters potenziell zu mindern. Eine mehrcloud-aktive/aktive Bereitstellungsstrategie führt jedoch zu einer erheblichen Komplexität rund um CI/CD. Angesichts der Unterschiede bei den Ressourcenspezifikationen und -funktionen zwischen Cloudanbietern benötigen Sie außerdem spezielle Bereitstellungsstempel für jede Cloud.

  • Geografische Verteilung. Die Workload kann Complianceanforderungen für die geografische Datenaufbewahrung, den Datenschutz und die Datenaufbewahrung aufweisen. Überlegen Sie, ob es bestimmte Regionen gibt, in denen Sich Daten befinden müssen oder wo Ressourcen bereitgestellt werden müssen.

  • Anforderungsursprung. Die geografische Nähe und Dichte von Benutzern oder abhängigen Systemen sollte Designentscheidungen über die globale Verteilung informieren.

  • Konnektivität: Wie auf die Workload von Benutzern oder externen Systemen zugegriffen wird, beeinflusst Ihr Design. Überlegen Sie, ob die Anwendung über das öffentliche Internet oder private Netzwerke verfügbar ist, die VPN- oder Azure ExpressRoute-Schaltkreise verwenden.

Designempfehlungen und Konfigurationsoptionen auf Plattformebene finden Sie unter Anwendungsplattform: Globale Verteilung.

Lose gekoppelte ereignisgesteuerte Architektur

Kopplung ermöglicht die Interservice-Kommunikation über gut definierte Schnittstellen. Eine lose Kopplung ermöglicht es einer Anwendungskomponente, unabhängig zu arbeiten. Ein Microservices-Architekturstil entspricht den unternehmenskritischen Anforderungen. Sie erleichtert hohe Verfügbarkeit, indem kaskadierende Fehler vermieden werden.

Für lose Kopplung empfehlen wir dringend, ereignisgesteuertes Design zu integrieren. Die asynchrone Nachrichtenverarbeitung über einen Vermittler kann Resilienz schaffen.

Diagramm, das die asynchrone ereignisgesteuerte Kommunikation veranschaulicht.

In einigen Szenarien können Anwendungen lose und enge Kopplungen kombinieren, je nach Geschäftszielen.

Überlegungen zum Entwurf

  • Laufzeitabhängigkeiten. Lose gekoppelte Dienste sollten nicht auf die Verwendung derselben Computeplattform, Programmiersprache, Laufzeit oder des Betriebssystems beschränkt werden.

  • Skalierung. Dienste sollten unabhängig voneinander skaliert werden können. Optimieren Sie die Nutzung von Infrastruktur- und Plattformressourcen.

  • Fehlertoleranz. Fehler sollten separat behandelt werden und sollten keine Auswirkungen auf Clienttransaktionen haben.

  • Transaktionsintegrität. Berücksichtigen Sie die Auswirkungen der Datenerstellung und Persistenz, die in separaten Diensten auftritt.

  • Verteilte Ablaufverfolgung: End-to-End-Ablaufverfolgung erfordert möglicherweise eine komplexe Orchestrierung.

Entwurfsempfehlungen

  • Richten Sie Microservice-Grenzen an kritischen Benutzerflüssen aus.

  • Verwenden Sie ereignisgesteuerte asynchrone Kommunikation, wenn möglich, um nachhaltige Skalierung und optimale Leistung zu unterstützen.

  • Verwenden Sie Muster wie Postausgang und Transaktionssitzung, um Konsistenz zu gewährleisten, damit jede Nachricht ordnungsgemäß verarbeitet wird.

Beispiel: Ereignisgesteuerter Ansatz

Die Mission-Critical Online-Referenzimplementierung verwendet Microservices, um eine einzelne Geschäftstransaktion zu verarbeiten. Sie wendet Schreibvorgänge asynchron mit einem Nachrichtenbroker und -worker an. Lesevorgänge sind synchron, wobei das Ergebnis direkt an den Aufrufer zurückgegeben wird.

Diagramm, das die ereignisgesteuerte Kommunikation zeigt.

Resilienzmuster und Fehlerbehandlung im Anwendungscode

Eine unternehmenskritische Anwendung muss so konzipiert sein, dass sie so viele Ausfallszenarien wie möglich behandelt. Diese Resilienz maximiert die Dienstverfügbarkeit und Zuverlässigkeit. Die Anwendung sollte über Selbstheilungsfunktionen verfügen, die Sie mithilfe von Entwurfsmustern wie Wiederholungsmustern mit Backoff und Circuit Breaker implementieren können.

Bei nicht vorübergehenden Fehlern, die Sie in der Anwendungslogik nicht vollständig mindern können, müssen das Integritätsmodell und die Betriebswrapper Korrekturmaßnahmen ergreifen. Der Anwendungscode muss geeignete Instrumentierung und Protokollierung enthalten, um das Integritätsmodell zu informieren und nachfolgende Problembehandlungen oder Ursachenanalysen nach Bedarf zu erleichtern. Sie müssen die verteilte Ablaufverfolgung implementieren, um dem Aufrufer eine umfassende Fehlermeldung bereitzustellen, die eine Korrelations-ID enthält, wenn ein Fehler auftritt.

Tools wie Application Insights können Ihnen helfen, Anwendungsablaufverfolgungen abzufragen, zu korrelieren und zu visualisieren.

Überlegungen zum Entwurf

  • Richtige Konfigurationen. Es ist nicht ungewöhnlich, dass vorübergehende Probleme kaskadierende Fehler verursachen. Beispielsweise verschlimmert der Wiederholungsversuche ohne entsprechendes Back-Off das Problem, wenn ein Dienst gedrosselt wird. Sie können die Wiederholungsversuche linear verzögern oder exponentiell erhöhen, um sie durch wachsende Verzögerungen wieder aufzuheben.

  • Integritätsendpunkte. Sie können funktionsbezogene Überprüfungen im Anwendungscode verfügbar machen, indem Sie Integritätsendpunkte verwenden, die externe Lösungen abrufen können, um den Integritätsstatus der Anwendungskomponente abzurufen.

Entwurfsempfehlungen

Im Folgenden finden Sie einige gängige Software engineering-Muster für robuste Anwendungen:

Muster Zusammenfassung
Warteschlangenbasierter Lastenausgleich Führt einen Puffer zwischen Verbrauchern und angeforderten Ressourcen ein, um konsistente Ladestufen sicherzustellen. Wenn Verbraucheranforderungen in die Warteschlange gestellt werden, verarbeitet ein Arbeitsprozess sie mit der angeforderten Ressource in einem Tempo, das vom Worker und von der Fähigkeit der angeforderten Ressource zum Verarbeiten der Anforderungen festgelegt wird. Wenn Verbraucher Antworten auf ihre Anforderungen erwarten, müssen Sie einen separaten Antwortmechanismus implementieren. Wenden Sie eine priorisierte Reihenfolge an, damit die wichtigsten Aktivitäten zuerst ausgeführt werden.
Sicherung Bietet Stabilität, indem entweder auf die Wiederherstellung gewartet oder Anforderungen schnell abgelehnt werden, anstatt zu blockieren, während auf einen nicht verfügbaren Remotedienst oder eine Ressource gewartet wird. Dieses Muster behandelt auch Fehler, die eine variable Zeit in Anspruch nehmen können, um wiederherzustellen, wenn eine Verbindung mit einem Remotedienst oder einer Ressource hergestellt wird.
Bulkhead Es wird versucht, Dienstinstanzen basierend auf Last- und Verfügbarkeitsanforderungen in Gruppen zu partitionieren und Fehler zu isolieren, um die Dienstfunktionalität aufrechtzuerhalten.
Saga Verwaltet die Datenkonsistenz über Microservices hinweg, die unabhängige Datenspeicher aufweisen, indem sichergestellt wird, dass Dienste über definierte Ereignis- oder Nachrichtenkanäle miteinander aktualisiert werden. Jeder Dienst führt lokale Transaktionen aus, um seinen eigenen Zustand zu aktualisieren und veröffentlicht ein Ereignis, um die nächste lokale Transaktion in der Saga auszulösen. Wenn ein Dienstupdate fehlschlägt, führt die Saga Ausgleichstransaktionen durch, um vorangehenden Dienstaktualisierungsschritten entgegenzuwirken. Einzelne Dienstupdateschritte können selbst Resilienzmuster implementieren, z. B. Wiederholungsversuche.
Überwachung des Integritätsendpunkts Implementiert funktionale Prüfungen in einer Anwendung, auf die externe Tools in regelmäßigen Abständen über verfügbar gemachte Endpunkte zugreifen können. Sie können Antworten von den Endpunkten interpretieren, indem Sie wichtige Betriebsmetriken verwenden, um den Anwendungsstatus zu informieren und operative Reaktionen auszulösen, z. B. das Auslösen einer Warnung oder das Ausführen einer ausgleichenden Rollbackbereitstellung.
Wiederholen Behandelt vorübergehende Fehler elegant und transparent.
– Abbrechen, wenn der Fehler unwahrscheinlich ist, dass er vorübergehend ist und nicht erfolgreich ist, wenn der Vorgang erneut versucht wird.
- Versuchen Sie es erneut, wenn der Fehler ungewöhnlich oder selten ist und der Vorgang wahrscheinlich erfolgreich ist, wenn der Versuch sofort erneut ausgeführt wird.
- Wiederholen Sie den Vorgang nach einer Verzögerung, wenn der Fehler durch eine Bedingung verursacht wird, die möglicherweise eine kurze Zeit für die Wiederherstellung benötigt, z. B. Netzwerkkonnektivität oder Hochlastfehler. Wenden Sie eine geeignete Back-Off-Strategie an, wenn wiederholungsverzögerte Verzögerungen steigen.
Drosselung Steuert den Verbrauch von Ressourcen, die von Anwendungskomponenten verwendet werden, und schützt sie davor, überlastet zu werden. Wenn eine Ressource einen Ladeschwellenwert erreicht, werden Vorgänge mit niedrigerer Priorität zurückgestellt und nicht wesentliche Funktionen beeinträchtigt, sodass die wesentlichen Funktionen fortgesetzt werden können, bis genügend Ressourcen verfügbar sind, um zum normalen Betrieb zurückzukehren.

Hier sind einige zusätzliche Empfehlungen:

  • Verwenden Sie vom Anbieter bereitgestellte SDKs wie die Azure-SDKs, um eine Verbindung mit abhängigen Diensten herzustellen. Verwenden Sie integrierte Resilienzfunktionen, anstatt benutzerdefinierte Funktionen zu implementieren.

  • Wenden Sie beim Wiederholen fehlgeschlagener Abhängigkeitsaufrufe eine geeignete Back-Off-Strategie an, um ein selbstverrichtetes DDoS-Szenario zu vermeiden.

  • Definieren Sie allgemeine Technische Kriterien für alle Anwendungs-Microservice-Teams, um Konsistenz und Geschwindigkeit bei der Verwendung von Resilienzmustern auf Anwendungsebene zu fördern.

  • Implementieren Sie Resilienzmuster mithilfe bewährter standardisierter Pakete wie Polly für C# oder Sentinel für Java.

  • Verwenden Sie Korrelations-IDs für alle Ablaufverfolgungsereignisse und Protokollmeldungen, um sie mit einer bestimmten Anforderung zu verknüpfen. Geben Sie nicht nur bei Anforderungen, bei denen ein Fehler aufgetreten ist, sondern bei allen Aufrufen Korrelations-IDs zurück.

  • Verwenden Sie die strukturierte Protokollierung für alle Protokollnachrichten. Wählen Sie eine einheitliche Betriebsdatensenke für Anwendungsablaufverfolgungen, Metriken und Protokolle aus, um Operatoren das einfache Debuggen von Problemen zu ermöglichen. Weitere Informationen finden Sie unter Sammeln, Aggregieren und Speichern von Überwachungsdaten für Cloudanwendungen.

  • Stellen Sie sicher, dass Betriebsdaten zusammen mit geschäftsspezifischen Anforderungen verwendet werden, um ein Anwendungsintegritätsmodell zu informieren.

Auswahl der Programmiersprache

Es ist wichtig, die richtigen Programmiersprachen und Frameworks auszuwählen. Diese Entscheidungen werden häufig von den Qualifikationssätzen oder standardisierten Technologien in der Organisation gesteuert. Es ist jedoch wichtig, die Leistung, Resilienz und die Gesamtfunktionen verschiedener Sprachen und Frameworks zu bewerten.

Überlegungen zum Entwurf

  • Development Kit-Funktionen. Es gibt Unterschiede in den Funktionen, die von Azure-Dienst-SDKs in verschiedenen Sprachen angeboten werden. Diese Unterschiede können die Wahl eines Azure-Diensts oder einer Programmiersprache beeinflussen. Wenn Azure Cosmos DB beispielsweise eine machbare Option ist, ist Go möglicherweise keine geeignete Entwicklungssprache, da kein First-Party-SDK vorhanden ist.

  • Featureupdates. Überlegen Sie, wie oft das SDK mit neuen Features für die ausgewählte Sprache aktualisiert wird. Häufig verwendete SDKs wie .NET- und Java-Bibliotheken werden häufig aktualisiert. Andere SDKs oder SDKs für andere Sprachen werden möglicherweise weniger häufig aktualisiert.

  • Mehrere Programmiersprachen oder Frameworks. Sie können mehrere Technologien verwenden, um verschiedene zusammengesetzte Workloads zu unterstützen. Sie sollten jedoch eine Zersprügelung vermeiden, da sie Die Verwaltungskomplexität und operative Herausforderungen einführt.

  • Berechnungsoption. Ältere oder proprietäre Software werden möglicherweise nicht in PaaS-Diensten ausgeführt. Außerdem können Sie möglicherweise keine Legacy- oder proprietäre Software in Container einschließen.

Entwurfsempfehlungen

  • Bewerten Sie alle relevanten Azure-SDKs für die benötigten Funktionen und ihre ausgewählten Programmiersprachen. Überprüfen Sie die Ausrichtung mit nicht funktionalen Anforderungen.

  • Optimieren Sie die Auswahl von Programmiersprachen und Frameworks auf Mikroservice-Ebene. Verwenden Sie nach Bedarf mehrere Technologien.

  • Priorisieren Sie das .NET SDK, um Zuverlässigkeit und Leistung zu optimieren. .NET Azure SDKs bieten in der Regel mehr Funktionen und werden häufig aktualisiert.

Nächster Schritt

Überprüfen Sie die Überlegungen für die Anwendungsplattform.