Bearbeiten

Freigeben über


Modern Web App-Muster für Java

Azure App Service
Azure-Servicebus

In diesem Artikel wird beschrieben, wie Sie das Modern Web App-Muster implementieren. Das Modern Web App-Muster definiert, wie Cloud-Web-Apps modernisiert und eine dienstorientierte Architektur eingeführt werden. Das Muster stellt präscriptive Architektur, Code und Konfigurationsanleitungen bereit, die den Prinzipien des Azure Well-Architected Framework-entsprechen. Dieses Muster basiert auf dem Zuverlässigen Web App-Muster.

Gründe für die Verwendung des modernen Web-App-Musters

Mit dem Muster "Modern Web App" können Sie bereiche mit hoher Nachfrage Ihrer Webanwendung optimieren. Es enthält detaillierte Anleitungen zum Entkoppeln dieser Bereiche, um eine unabhängige Skalierung für die Kostenoptimierung zu ermöglichen. Mit diesem Ansatz können Sie dedizierte Ressourcen kritischen Komponenten zuordnen, wodurch die Gesamtleistung verbessert wird. Die Entkoppelung separierbarer Dienste kann die Zuverlässigkeit verbessern, indem verlangsamte Verzögerungen in einem Teil der App nicht beeinträchtigt werden. Sie ermöglicht auch die unabhängige Versionsverwaltung einzelner App-Komponenten.

Implementieren des modernen Web-App-Musters

Dieser Artikel enthält Anleitungen für die Implementierung des Modern Web App-Musters. Verwenden Sie die folgenden Links, um zu den spezifischen Anleitungen zu wechseln, die Sie benötigen:

  • 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

GitHub-Logo Es gibt eine Referenzimplementierung (Beispiel-App) des Modern Web App-Musters. Sie stellt den Endzustand der Modern Web App-Implementierung dar. Es handelt sich um eine Web-App mit Produktionsqualität, die alle Code-, Architektur- und Konfigurationsupdates enthält, die in diesem Artikel erläutert werden. 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. Es erfordert einige zusätzliche Architekturkomponenten. Sie benötigen eine Nachrichtenwarteschlange, Containerplattform, Speicherdienst und Containerregistrierung, wie im folgenden Diagramm dargestellt:

Diagramm mit der Basisarchitektur des Modern Web App-Musters.

Für ein höheres Ziel auf Dienstebene (SLO) können Sie Ihrer Web-App-Architektur eine zweite Region hinzufügen. Konfigurieren Sie Ihren Lastenausgleich so, dass der Datenverkehr an die zweite Region weitergeleitet wird, um abhängig von Ihren Geschäftlichen Anforderungen entweder eine aktive oder eine passive Konfiguration zu unterstützen. Für die beiden Regionen sind dieselben Dienste erforderlich, mit Ausnahme einer Region, die über ein virtuelles Hubnetzwerk verfügt. 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 zeigt diese Architektur:

Diagramm mit der Modern Web App-Musterarchitektur mit einer zweiten Region.

Entkoppeln der Architektur

Um das moderne Web-App-Muster zu implementieren, müssen Sie die vorhandene Web-App-Architektur entkoppeln. Die Entkoppelung der Architektur erfordert, dass eine monolithische Anwendung in kleinere, unabhängige Dienste aufgeteilt wird, die jeweils für ein bestimmtes Feature oder eine bestimmte Funktion verantwortlich sind. Dieser Prozess umfasst 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 ist ein Kandidat für die Entkoppelung. Dienste, die unterschiedliche Geschäftsfunktionen darstellen und weniger Abhängigkeiten aufweisen, sind gute Kandidaten.

  • Evaluieren Sie die Dienstvorteile. Konzentrieren Sie sich auf Dienste, die am meisten von der unabhängigen Skalierung profitieren. Eine externe Abhängigkeit wie z. B. ein E-Mail-Dienstanbieter in einer BRANCHENanwendung erfordert möglicherweise eine größere Isolation vom Fehler. Erwägen Sie Dienste, die häufig aktualisiert oder geändert werden. Die Entkoppelung dieser Dienste ermöglicht eine unabhängige Bereitstellung und reduziert das Risiko, andere Teile der Anwendung zu beeinträchtigen.

  • 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 freigegeben 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 im Abschnitt Auswählen der richtigen Azure-Dienste Abschnitt dieses Artikels.

  • Entkoppeln Sie den Web-App-Dienst. Definieren Sie klare Schnittstellen und APIs, mit denen die neu extrahierten Webdienste für die Interaktion mit anderen Teilen des Systems verwendet werden können. Entwerfen Sie eine Datenverwaltungsstrategie, mit der jeder Dienst seine eigenen Daten verwalten kann, aber Konsistenz und Integrität gewährleistet. Spezifische Implementierungsstrategien und Entwurfsmuster, die während dieses Extraktionsprozesses verwendet werden sollen, finden Sie im Abschnitt Codeleitfaden.

  • Verwenden Sie einen unabhängigen Speicher für entkoppelte Dienste. Um die Versionsverwaltung und Bereitstellung zu vereinfachen, stellen Sie sicher, dass jeder entkoppelte Dienst über eigene Datenspeicher verfügt. Die Referenzimplementierung trennt z. B. den E-Mail-Dienst von der Web-App und beseitigt die Notwendigkeit, dass der Dienst auf die Datenbank zugreifen kann. Stattdessen kommuniziert der Dienst den E-Mail-Zustellungsstatus über eine Azure Service Bus-Nachricht zurück an die Web-App, und die Web-App speichert eine Notiz in der Datenbank.

  • Implementieren Sie separate Bereitstellungspipelines für jeden entkoppelten Dienst. Wenn Sie separate Bereitstellungspipelines implementieren, kann jeder Dienst entsprechend seinem eigenen Zeitplan aktualisiert werden. Wenn verschiedene Teams oder Organisationen innerhalb Ihres Unternehmens unterschiedliche Dienste besitzen, bietet die Verwendung separater Bereitstellungspipelinen 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 Service Bus. Beginnen Sie mit Service Bus, und verwenden Sie eine der beiden anderen Optionen, wenn Service Bus Ihre Anforderungen nicht erfüllt.

    Dienst Anwendungsfall
    Service Bus Wählen Sie Service Bus für eine zuverlässige, sortierte und möglicherweise transaktionsbezogene Zustellung von hochwertigen Nachrichten in Unternehmensanwendungen aus.
    Event Grid 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. Ressourcenstatusänderungen) in einem Veröffentlichungsabonnementmodell mit geringer Latenz an Abonnenten weitergeleitet werden müssen.
    Event 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 Elemente Ihrer Anwendung, die Sie containerisieren möchten, benötigen Sie eine Anwendungsplattform, die Container unterstützt. Der Auswählen eines Azure-Containerdiensts Anleitungen kann Ihnen bei der Auswahl helfen. Azure verfügt über drei Prinzipalcontainerdienste: Azure Container Apps, Azure Kubernetes Service (AKS) und Azure-App Service. Beginnen Sie mit Container-Apps, und verwenden Sie eine der beiden anderen 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 App 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. Der Leitfaden Einführung in Containerregistrierungen in Azure kann Ihnen bei der Auswahl helfen.

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, Queue-Based Load Leveling, Konkurrierende Verbraucher, Health Endpoint Monitoring und Wiederholen. Das folgende Diagramm zeigt die Rollen dieser Muster:

Diagramm mit der Rolle der Entwurfsmuster in der Modern Web App-Musterarchitektur.

  1. 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.

  2. 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 im Produzententeil des entkoppelten Diensts, um den Nachrichtenfluss asynchron mithilfe einer Warteschlange zu verwalten.

  3. Konkurrierende Verbraucher muster: Das Muster "Konkurrierende Verbraucher" ermöglicht es mehreren Instanzen eines entkoppelten Diensts, unabhängig von derselben Nachrichtenwarteschlange zu lesen und nachrichten zu verarbeiten. Implementieren Sie dieses Muster im entkoppelten Dienst, um Aufgaben über mehrere Instanzen hinweg zu verteilen.

  4. Muster für die Integritätsendpunktüberwachung: Das Integritätsendpunktüberwachungsmuster macht Endpunkte zur Überwachung des Status und der Integrität verschiedener Komponenten 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.

  5. Wiederholungsmuster: Das Wiederholungsmuster behandelt vorübergehende Fehler durch Wiederholungsvorgänge, die zeitweise fehlschlagen können. (5a) Implementieren Sie dieses Muster in der Hauptweb-App für alle ausgehenden Anrufe an andere Azure-Dienste, 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. Die folgende Tabelle enthält Details.

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“ Hersteller des entkoppelten Dienstes RE:06
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 /users Endpunkt in Ihrer monolithischen App haben und diese Funktionalität in den entkoppelten Dienst verschieben, leitet die Routingebene alle Anforderungen an /users an den neuen Dienst weiter.

  • Verwalten des Featurerollouts.Implementieren Sie Featurekennzeichnungen und mehrstufiges Rollout , 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 Diensts.

    Beispielsweise extrahiert die Referenzimplementierung die E-Mail-Zustellungsfunktion in einen eigenständigen Dienst. Der Dienst kann schrittweise eingeführt werden, um einen größeren Prozentsatz der Anforderungen zum Senden von E-Mails zu verarbeiten, die Contoso-Supporthandbücher enthalten. Da der neue Dienst seine Zuverlässigkeit und Leistung beweist, kann er schließlich die gesamte Reihe von E-Mail-Verantwortlichkeiten 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 sicher, dass der neue entkoppelte Dienst Anforderungen unabhängig verarbeiten kann, wenn er über die Fassade aufgerufen 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. Er ermöglicht es dem entkoppelten Dienst, Anforderungen mit einer konsistenten Rate zu verarbeiten. 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, andere Prozesse nicht blockiert, während der entkoppelte Dienst wartet, um Nachrichten in der Warteschlange zu verarbeiten. Wenn der Prozess das Ergebnis des decoupled-Service-Vorgangs erfordert, implementieren Sie eine alternative Möglichkeit, die Situation zu behandeln, während sie auf den Abschluss des in die Warteschlange eingereihten Vorgangs wartet. Beispielsweise können Sie im Spring Boot die StreamBridge Klasse verwenden, um Nachrichten asynchron in der Warteschlange zu veröffentlichen, ohne den aufrufenden Thread zu blockieren:

    private final StreamBridge streamBridge;
    
    public SupportGuideQueueSender(StreamBridge streamBridge) {
        this.streamBridge = streamBridge;
    }
    
    // Asynchronously publish a message without blocking the calling thread
    @Override
    public void send(String to, String guideUrl, Long requestId) {
        EmailRequest emailRequest = EmailRequest.newBuilder()
                .setRequestId(requestId)
                .setEmailAddress(to)
                .setUrlToManual(guideUrl)
                .build();
    
        log.info("EmailRequest: {}", emailRequest);
    
        var message = emailRequest.toByteArray();
        streamBridge.send(EMAIL_REQUEST_QUEUE, message);
    
        log.info("Message sent to the queue");
    }
    

    In diesem Java-Beispiel werden StreamBridge Nachrichten asynchron gesendet. Mit diesem Ansatz wird sichergestellt, dass die Hauptanwendung reaktionsfähig bleibt und gleichzeitig andere Aufgaben verarbeiten kann, während der entkoppelte Dienst die in die Warteschlange gestellten Anforderungen in einer verwaltbaren 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 verarbeiten, in denen eine Nachricht mehrmals verarbeitet werden kann. Im Spring Boot können Sie einen eindeutigen Nachrichtenbezeichner verwenden @StreamListener oder @KafkaListener verwenden, um doppelte Verarbeitung zu verhindern. Oder Sie können den Geschäftsprozess so organisieren, dass er in einem funktionalen Ansatz mit Spring Cloud Stream arbeitet, bei dem die consume Methode auf eine Weise definiert wird, die dasselbe Ergebnis erzeugt, wenn sie wiederholt ausgeführt wird. Eine Liste der Einstellungen, die das Verhalten der Nachrichtennutzung verwalten, finden Sie unter Spring Cloud Stream mit Service Bus.

  • Verwalten Sie Änderungen an der Benutzeroberfläche. Wenn Sie asynchrone Verarbeitung verwenden, werden Aufgaben möglicherweise nicht sofort abgeschlossen. Um Erwartungen festzulegen und Verwirrung zu vermeiden, stellen Sie sicher, dass Benutzer wissen, wann ihre Aufgaben noch verarbeitet werden. 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" im entkoppelten Dienst, 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. Das Muster verbessert den Lastenausgleich und erhöht die Kapazität des Systems für die 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, was bedeutet, dass er mehrmals angewendet werden kann, ohne das Ergebnis nach der ersten Anwendung zu ändern.

Befolgen Sie die folgenden Empfehlungen, um das Muster konkurrierender Verbraucher zu implementieren:

  • Verarbeiten Sie gleichzeitig eingehende Nachrichten. Wenn Dienste Nachrichten aus einer Warteschlange empfangen, stellen Sie sicher, dass Ihr System vorhersehbar skaliert wird, indem Sie die Parallelität so konfigurieren, dass sie mit dem Systementwurf übereinstimmt. Das Laden von Testergebnissen kann Ihnen dabei helfen, die entsprechende Anzahl gleichzeitiger Nachrichten zu ermitteln. Sie können von einer beginnen, um die Leistung des Systems zu messen.

  • Deaktivieren Sie das Vorabrufen. Deaktivieren Sie das Vorabfetchen von Nachrichten, sodass Verbraucher nur Nachrichten abrufen, wenn sie bereit sind.

  • Verwenden Sie zuverlässige Nachrichtenverarbeitungsmodi. Verwenden Sie einen zuverlässigen Verarbeitungsmodus, z. B. "Vorschausperre", mit dem Nachrichten, die nicht verarbeitet werden, automatisch erneut ausgeführt 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 problematische Nachrichten in die separate Warteschlange verschieben. Mit Service Bus werden Nachrichten nach einer angegebenen Anzahl von Zustellungsversuchen oder nach expliziter Ablehnung der Anwendung in die Warteschlange für tote Leter verschoben.

  • 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 mehrere parallele Consumer haben, verarbeiten sie möglicherweise Nachrichten außerhalb der Reihenfolge.

  • Skalieren Sie basierend auf der Warteschlangenlänge. Dienste, die Nachrichten aus einer Warteschlange nutzen, sollten basierend auf der Warteschlangenlänge automatisch skalieren. Die skalierungsbasierte automatische Skalierung ermöglicht eine effiziente Verarbeitung von Spitzen eingehender Nachrichten.

  • Verwenden Sie eine Nachrichtenantwortwarteschlange. Wenn Ihr 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. Dies ermöglicht 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 das Muster "Konkurrierende Verbraucher" für einen zustandslosen Dienst, der in Container-Apps ausgeführt wird, um E-Mail-Zustellungsanforderungen aus einer ServiceBus-Warteschlange zu verarbeiten.

Der Prozessor protokolliert Details zur Nachrichtenverarbeitung, um bei der Problembehandlung und Überwachung zu helfen. Es erfasst Deserialisierungsfehler und bietet Einblicke, die beim Debuggen nützlich sein können. Der Dienst wird auf Containerebene skaliert, um eine effiziente Behandlung von Nachrichtenspitzen basierend auf der Warteschlangenlänge zu ermöglichen. Hier ist der Code:

@Configuration
public class EmailProcessor {

    private static final Logger log = LoggerFactory.getLogger(EmailProcessor.class);

    @Bean
    Function<byte[], byte[]> consume() {
        return message -> {

            log.info("New message received");

            try {
                EmailRequest emailRequest = EmailRequest.parseFrom(message);
                log.info("EmailRequest: {}", emailRequest);

                EmailResponse emailResponse = EmailResponse.newBuilder()
                        .setEmailAddress(emailRequest.getEmailAddress())
                        .setUrlToManual(emailRequest.getUrlToManual())
                        .setRequestId(emailRequest.getRequestId())
                        .setMessage("Email sent to " + emailRequest.getEmailAddress() + " with URL to manual " + emailRequest.getUrlToManual())
                        .setStatus(Status.SUCCESS)
                        .build();

                return emailResponse.toByteArray();

            } catch (InvalidProtocolBufferException e) {
                throw new RuntimeException("Error parsing email request message", e);
            }
        };
    }
}

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. Spring Boot Actuator bietet integrierte Unterstützung für Integritätsprüfungen. Sie kann Integritätsprüfungsendpunkte für wichtige Abhängigkeiten wie Datenbanken, Nachrichtenbroker und Speichersysteme verfügbar machen. 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 Spring Boot Actuator, um Endpunkte für die Integritätsprüfung bereitzustellen. Der Aktor macht einen /actuator/health Endpunkt verfügbar, der integrierte Integritätsindikatoren und benutzerdefinierte Überprüfungen für verschiedene Abhängigkeiten enthält. Um den Integritätsendpunkt zu aktivieren, fügen Sie die spring-boot-starter-actuator Abhängigkeit in Der datei pom.xml oder build.gradle hinzu:

    <!-- Add Spring Boot Actuator dependency -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    Konfigurieren Sie den Integritätsendpunkt in application.properties wie in der Referenzimplementierung gezeigt:

        management.endpoints.web.exposure.include=metrics,health,info,retry,retryevents
    
  • Überprüfen Sie Abhängigkeiten. Spring Boot Actuator enthält Integritätsindikatoren für verschiedene Abhängigkeiten wie Datenbanken, Nachrichtenbroker (RabbitMQ oder Kafka) und Speicherdienste. Um die Verfügbarkeit von Azure-Diensten wie Azure Blob Storage oder Service Bus zu überprüfen, verwenden Sie Technologien wie Azure Spring Apps oder Micrometer, die Integritätsindikatoren für diese Dienste bereitstellen. Wenn Sie benutzerdefinierte Prüfungen benötigen, können Sie diese implementieren, indem Sie eine benutzerdefinierte HealthIndicator Bean erstellen:

    import org.springframework.boot.actuate.health.Health;
    import org.springframework.boot.actuate.health.HealthIndicator;
    import org.springframework.stereotype.Component;
    
    @Component
    public class CustomAzureServiceBusHealthIndicator implements HealthIndicator {
        @Override
        public Health health() {
            // Implement your health check logic here (for example, ping Service Bus).
            boolean isServiceBusHealthy = checkServiceBusHealth();
            return isServiceBusHealthy ? Health.up().build() : Health.down().build();
        }
    
        private boolean checkServiceBusHealth() {
            // Implement health check logic (pinging or connecting to the service).
            return true; // Placeholder. Implement the actual logic.
        }
    }
    
  • Konfigurieren Sie Azure-Ressourcen. Konfigurieren Sie die Azure-Ressource, um die Integritätsprüfungs-URLs der App zu verwenden, um die Liveheit und Bereitschaft zu bestätigen. Beispielsweise können Sie Terraform verwenden, um die Liveität und Bereitschaft von Apps zu bestätigen, die für Container-Apps bereitgestellt werden. Weitere Informationen finden Sie unter Integritätssonden in Container-Apps.

Implementieren des Wiederholungsmusters

Das Wiederholungsmusters ermöglicht Anwendungen das Wiederherstellen von vorübergehenden Fehlern. Dieses Muster ist für das zuverlässige Web App-Muster von zentraler Bedeutung. Daher sollte Ihre Web-App bereits das Wiederholungsmuster verwenden. Wenden Sie das Wiederholungsmuster auf Anforderungen an die Messagingsysteme und Anforderungen an, die von den decoupierten Diensten ausgegeben werden, die Sie aus der Web-App extrahieren. Befolgen Sie die folgenden Empfehlungen, um das Wiederholungsmuster zu implementieren:

  • Konfigurieren Sie Wiederholungsoptionen. Konfigurieren Sie unbedingt den Client, der für Interaktionen mit der Nachrichtenwarteschlange 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 die exponentielle Backoff-Strategie 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. Diese integrierten Mechanismen sind für die typischen Anwendungsfälle des Diensts optimiert, können Wiederholungen effektiver verarbeiten und weniger Konfiguration erfordern.

  • Verwenden Sie Standardresilienzbibliotheken für HTTP-Clients. Für HTTP-Clients können Sie Resilienz4j zusammen mit Spring's RestTemplate oder WebClient verwenden, um Wiederholungen in der HTTP-Kommunikation zu verarbeiten. Sie können RestTemplate mit der Wiederholungslogik von Resilience4j umschließen, um vorübergehende HTTP-Fehler effektiv zu behandeln.

  • Behandeln Sie die Nachrichtensperre. Implementieren Sie für nachrichtenbasierte Systeme Strategien zur Nachrichtenverarbeitung, die Wiederholungen ohne Datenverlust unterstützen. Verwenden Sie z. B. Vorschausperrmodi, wenn sie verfügbar sind. Stellen Sie sicher, dass fehlgeschlagene Nachrichten effektiv wiederholt und nach wiederholten Fehlern in eine Warteschleife verschoben werden.

Anleitung zur Konfiguration

In den folgenden Abschnitten finden Sie Anleitungen für die Implementierung der Konfigurationsupdates. Jeder Abschnitt richtet sich an einer oder mehreren Säulen des Well-Architected Frameworks.

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 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. Dadurch wird der potenzielle Schaden begrenzt, wenn eine Identität kompromittiert wird.

  • Verwenden Sie die Infrastruktur als Code (IaC). Verwenden Sie Bicep oder ein ähnliches IaC-Tool wie Terraform, 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 Benutzer nur über die Berechtigungen verfügen, 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 und unnötigen Berechtigungen, und korrigieren Oder entfernen 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 durch Definieren von Rollen für Containerregistrierungspushs und Pulls. Hier ist der Code:

resource "azurerm_role_assignment" "container_app_acr_pull" {
  principal_id         = var.aca_identity_principal_id
  role_definition_name = "AcrPull"
  scope                = azurerm_container_registry.acr.id
}

resource "azurerm_user_assigned_identity" "container_registry_user_assigned_identity" {
  name                = "ContainerRegistryUserAssignedIdentity"
  resource_group_name = var.resource_group
  location            = var.location
}

resource "azurerm_role_assignment" "container_registry_user_assigned_identity_acr_pull" {
  scope                = azurerm_container_registry.acr.id
  role_definition_name = "AcrPull"
  principal_id         = azurerm_user_assigned_identity.container_registry_user_assigned_identity.principal_id
}


# For demo purposes, allow the current user to access the container registry.
# Note: When running as a service principal, this is also needed.
resource "azurerm_role_assignment" "acr_contributor_user_role_assignement" {
  scope                = azurerm_container_registry.acr.id
  role_definition_name = "Contributor"
  principal_id         = data.azuread_client_config.current.object_id
}

Konfigurieren der unabhängigen automatischen Skalierung

Das Modern Web App-Muster beginnt mit dem Aufbrechen der monolithischen Architektur und führt die Dienstkopplung 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 Web-App den sitzungsinternen Zustand 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 wie Kubernetes Event-Driven Autoscaler (KEDA) häufig präzise Kontrolle, 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 automatischen Skalierungsfeatures, die von der Plattform selbst bereitgestellt werden. Diese Features umfassen häufig die Skalierung basierend auf metrikbasierten Regeln oder HTTP-Datenverkehr.

  • Konfigurieren Sie Mindestreplikate. Um Kaltstarts zu verhindern, konfigurieren Sie die Einstellungen für die automatische Skalierung, um mindestens ein Replikat beizubehalten. Ein Kaltstart ist die Initialisierung eines Diensts aus einem angehaltenen Zustand. Ein Kaltstart verzögert häufig die Antwort. 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 Lastspitzen ausgelöst werden.

  • Konfigurieren Sie die warteschlangenbasierte Skalierung. Wenn Ihre Anwendung eine Nachrichtenwarteschlange wie Service Bus verwendet, konfigurieren Sie die Einstellungen für die automatische Skalierung basierend auf der Länge der Anforderungsnachrichtenwarteschlange. Der Scaler versucht, ein Replikat des Diensts für jede N- Nachrichten in der Warteschlange beizubehalten (aufgerundet).

Die Referenzimplementierung verwendet z. B. den Service Bus KEDA-Scaler, um container-App basierend auf der Länge der ServiceBus-Warteschlange automatisch zu skalieren. Die Skalierungsregel namens service-bus-queue-length-rulepasst die Anzahl der Dienstreplikate basierend auf der Nachrichtenanzahl in der angegebenen Servicebus-Warteschlange an. Der messageCount-Parameter ist auf 10 festgelegt, wodurch der Scaler ein Replikat für alle 10 Nachrichten in der Warteschlange hinzugefügt wird. Die maximale Replikatanzahl (max_replicas) ist auf 10 festgelegt. Die minimale Replikatanzahl ist implizit 0, es sei denn, sie wird außer Kraft gesetzt. Mit dieser Konfiguration kann der Dienst auf Null skaliert werden, wenn keine Nachrichten in der Warteschlange vorhanden sind. Die Verbindungszeichenfolge für die Servicebus-Warteschlange wird als geheimer Schlüssel in Azure gespeichert, der als azure-servicebus-connection-stringbezeichnet wird, der zum Authentifizieren des Scalers für den ServiceBus verwendet wird. Hier ist der Terraform-Code:

    max_replicas = 10
    min_replicas = 1

    custom_scale_rule {
      name             = "service-bus-queue-length-rule"
      custom_rule_type = "azure-servicebus"
      metadata = {
        messageCount = 10
        namespace    = var.servicebus_namespace
        queueName    = var.email_request_queue_name
      }
      authentication {
        secret_name       = "azure-servicebus-connection-string"
        trigger_parameter = "connection"
      }
    }

Containerisieren der Dienstbereitstellung

Die Containerisierung ist die Kapselung aller Abhängigkeiten, die von der App in einem einfachen Image benötigt werden, das zuverlässig in einer 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 Java-Dienste erstellen, verwenden Sie offizielle OpenJDK-Basisimages. Diese Images enthalten nur den minimalen Satz von Paketen, die Java ausführen muss. Die Verwendung dieser Bilder minimiert sowohl die Paketgröße als auch den Angriffsfläche.

  • Verwenden Sie mehrstufige Dockerfiles. Verwenden Sie eine mehrstufige Dockerfile-Datei, um Buildzeitressourcen vom Laufzeitcontainerimage zu trennen. Die Verwendung dieser Dateiart trägt dazu bei, dass Ihre Produktionsimages klein und sicher bleiben. Sie können auch einen vorkonfigurierten Buildserver verwenden und die JAR-Datei in das Containerimage kopieren.

  • Führen Sie die Ausführung als nichtroot-Benutzer aus. Führen Sie Ihre Java-Container als nicht entstammten 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, die die App benötigt, im Docker-Containerimage gekapselt werden. Die Kapselung ermöglicht es der App, zuverlässig in einer Vielzahl von Hosts bereitgestellt zu werden.

  • Wählen Sie die richtigen Basisimages aus. Das ausgewählte Basisimage hängt von Ihrer Bereitstellungsumgebung ab. Wenn Sie beispielsweise für Container-Apps bereitstellen, müssen Sie Linux-Docker-Images verwenden.

Die Referenzimplementierung veranschaulicht einen Docker-Buildprozess zum Containerisieren einer Java-Anwendung. Die Dockerfile verwendet einen einzelstufigen Build mit dem OpenJDK-Basisimage (mcr.microsoft.com/openjdk/jdk:17-ubuntu), das die erforderliche Java-Laufzeitumgebung bereitstellt.

Die Dockerfile-Datei enthält die folgenden Schritte:

  1. Deklarieren des Volumes. Ein temporäres Volume (/tmp) wird definiert. Dieses Volume bietet temporären Dateispeicher, der vom Hauptdateisystem des Containers getrennt ist.
  2. Kopieren von Artefakten. Die JAR-Datei der Anwendung (email-processor.jar) wird zusammen mit dem Application Insights-Agent (applicationinsights-agent.jar) in den Container kopiert, der für die Überwachung verwendet wird.
  3. Festlegen des Einstiegspunkts. Der Container ist so konfiguriert, dass die Anwendung mit aktivierter Application Insights-Agent ausgeführt wird. Der Code verwendet java -javaagent, um die Anwendung während der Laufzeit zu überwachen.

Die Dockerfile-Datei behält das Image klein, indem nur Laufzeitabhängigkeiten eingeschlossen werden. Es eignet sich für Bereitstellungsumgebungen wie Container-Apps, die Linux-basierte Container unterstützen.

# Use the OpenJDK 17 base image on Ubuntu as the foundation.
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu

# Define a volume to allow temporary files to be stored separately from the container's main file system.
VOLUME /tmp

# Copy the packaged JAR file into the container.
COPY target/email-processor.jar app.jar

# Copy the Application Insights agent for monitoring.
COPY target/agent/applicationinsights-agent.jar applicationinsights-agent.jar

# Set the entrypoint to run the application with the Application Insights agent.
ENTRYPOINT ["java", "-javaagent:applicationinsights-agent.jar", "-jar", "/app.jar"]

Bereitstellen der Referenzimplementierung

Stellen Sie die Referenzimplementierung des Modern Web App-Musters für Java 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:

Diagramm, das die Architektur der Referenzimplementierung zeigt.

Laden Sie eine Visio-Datei dieser Architektur herunter.