Bearbeiten

Freigeben über


Modern Web App-Muster für Java

Azure App Service
Azure Front Door
Azure Cache for Redis

In diesem Artikel erfahren Sie, wie Sie das moderne 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" trägt dazu bei, bereiche mit hoher Nachfrage Ihrer Webanwendung zu optimieren. Es bietet detaillierte Anleitungen, um diese Bereiche zu entkoppeln und eine unabhängige Skalierung für die Kostenoptimierung zu ermöglichen. Mit diesem Ansatz können Sie dedizierte Ressourcen kritischen Komponenten zuordnen und die Gesamtleistung verbessern. Durch die Entkoppelung separierbarer Dienste kann die Zuverlässigkeit verbessert werden, indem die Verlangsamung in einem Teil der App andere beeinträchtigt und die Versionsverwaltung einzelner App-Komponenten unabhängig voneinander aktiviert wird.

Implementieren des modernen Web-App-Musters

Dieser Artikel enthält Architektur-, Code- und Konfigurationsinformationen zum Implementieren des modernen Web-App-Musters. Verwenden Sie die folgenden Links, um zu den benötigten Anleitungen zu navigieren:

  • Architekturleitfaden: Erfahren Sie, wie Sie Web-App-Komponenten modularisieren und geeignete Plattform als Dienstlösungen (PaaS) auswählen.
  • Anleitung zu Code: Implementieren Sie vier Entwurfsmuster zur Optimierung der entkoppelten Komponenten: Strangler Fig, Warteschlangenbasiertes Lastenausgleich, Konkurrierende Verbraucher und Muster für Integritätsendpunktüberwachung.
  • Anleitung zur Konfiguration: Konfigurieren Sie die Authentifizierung, Autorisierung, automatische Skalierung und Containerisierung für die entkoppelten Komponenten.

Tipp

GitHub-Logo Es gibt eine Referenzimplementierung (Beispiel-App) des modernen Web-App-Musters. Sie stellt den Endzustand der Modern Web App-Implementierung 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, einen Speicherdienst und eine Containerregistrierung (siehe Abbildung 1).

Diagramm mit der Basisarchitektur des modernen Web-App-Musters.Abbildung 1. Grundlegende Architekturelemente des modernen 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 je nach Geschäftlichem Bedarf eine aktive oder 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, das eine Verbindung herstellt. Verwenden Sie eine Hub-and-Spoke-Netzwerktopologie, um freigegebene Ressourcen wie eine Netzwerkfirewall zu zentralisieren und gemeinsam zu nutzen. 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 sicher zu verwalten (siehe Abbildung 2).

Diagramm mit der Architektur des modernen Web-App-Musters mit zweiter Region und Hub-and-Spoke-Netzwerktopologie.Abbildung 2. Die Architektur des modernen Web-App-Musters mit zweiter Region und Hub-and-Spoke-Netzwerktopologie.

Entkopplungsarchitektur

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 Von Dienstgrenzen Wenden Sie domänengesteuerte Entwurfsprinzipien an, um begrenzungsgebundene 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. 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 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 zu extrahierenden Web-App-Dienst zu unterstützen, und stellen Sie sie bereit. Eine Anleitung dazu finden Sie im Abschnitt Auswählen des richtigen Azure-Dienstes.

  • Entkoppeln Sie den Web-App-Dienst. Definieren Sie klare Schnittstellen und APIs für die neu extrahierten Web-App-Dienste für die Interaktion mit anderen Teilen des Systems. 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 Abschnitt Anleitung zum Code.

  • Verwenden Sie einen unabhängigen Speicher für entkoppelte Dienste. Jeder entkoppelte Dienst sollte über eigene Datenspeicher verfügen, um die Versionsverwaltung und Bereitstellung zu vereinfachen. 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. 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 ein wichtiger Bestandteil 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 als Standardauswahl, und verwenden Sie die anderen beiden 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 Modell 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 Teile Ihrer Anwendung, die Sie containerisieren möchten, benötigen Sie eine Anwendungsplattform, die Container unterstützt. Verwenden Sie die Anleitung zum Auswählen eines Azure-Containerdiensts, um 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 im App-Dienst 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. Verwenden Sie die Einführung in Containerregistrierungen in Azure, um 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.

Diagramm, das die Rolle der Entwurfsmuster in der Architektur des modernen Web-App-Musters zeigt.Abbildung 3. Rolle der Entwurfsmuster.

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

  4. Ü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.

  5. 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 sich an einer oder mehreren Säulen des Well-Architected Framework ausrichten (siehe die folgende 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“ 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 & entkoppelter Dienst RE:07
RE:10
OE:07
PE:05
Wiederholungsmuster Hauptweb-App & entkoppelter Dienst RE:07

Implementieren des Strangler Fig-Musters

Verwenden Sie das Strangler-Feigenmuster , 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 verschoben haben, leitet die Routingebene alle Anforderungen an /users 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 erhalten. Beginnen Sie mit einem kleinen Prozentsatz an Anfragen und erhöhen Sie die Nutzung im Laufe der Zeit, wenn Sie Vertrauen in die Stabilität und Leistung gewonnen haben.

    Beispielsweise extrahiert die Referenzimplementierung die E-Mail-Zustellungsfunktion in einen eigenständigen Dienst, der schrittweise eingeführt werden kann, um einen größeren Teil der Anforderungen zum Senden von E-Mails mit Contoso-Supporthandbüchern zu verarbeiten. 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 im neuen entkoppelten Dienst sicher, dass er 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 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 (siehe Beispielcode):

    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 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. 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. Lesen Sie Spring Cloud Stream mit Service Bus für eine weitere Liste der Einstellungen, die das Verhalten der Nutzung von Nachrichten verwalten.

  • 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" 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, 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. Stellen Sie beim Empfangen von Nachrichten aus einer Warteschlange sicher, dass Ihr System vorhersehbar skaliert wird, indem Sie die Parallelität so konfigurieren, dass sie ihrem Systementwurf entspricht. Ihre Auslastungstestergebnisse helfen Ihnen bei der Entscheidung der geeigneten Anzahl gleichzeitiger Nachrichten, die behandelt werden sollen, und Sie können von einer beginnen, um die Leistung des Systems zu messen.

  • Deaktivieren Sie das Vorabrufen. Deaktivieren Sie das Vorabfetchen von Nachrichten, damit Verbraucher Nur Nachrichten 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 erhöht die Zuverlässigkeit gegenüber Methoden, bei denen zuerst gelöscht wird. 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, inaktive Warteschlange 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. Bei Service Bus werden Nachrichten nach einer bestimmten Anzahl von Zustellungsversuchen oder bei expliziter Ablehnung durch die Anwendung in die Warteschlange "dead-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. Mehrere parallele Verbraucher bedeuten, dass sie Nachrichten möglicherweise nicht mehr gemäß der Reihenfolge verarbeiten.

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

  • Verwenden Sie die 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. Dies ermöglicht eine einfache Skalierung und eine 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 die E-Mail-Zustellungsanforderungen aus einer ServiceBus-Warteschlange zu verarbeiten.

Der Prozessor protokolliert Details zur Nachrichtenverarbeitung und unterstützt die Problembehandlung und -überwachung. Er erfasst Deserialisierungsfehler und liefert Einblicke, die beim Debuggen des Prozesses erforderlich sind. Der Dienst wird auf Containerebene skaliert und ermöglicht eine effiziente Behandlung von Nachrichtenspitzen basierend auf der Warteschlangenlänge (siehe den folgenden 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 bietet integrierte Unterstützung für Integritätsprüfungen mit Spring Boot Actuator, die Endpunkte für die Integritätsprüfung für wichtige Abhängigkeiten wie Datenbanken, Nachrichtenbroker und Speichersysteme verfügbar machen können. 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. Spring Boot Actuator macht einen Endpunkt /actuator/health 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 Ihrer pom.xml Datei hinzu build.gradle .

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

    Konfigurieren Sie den Integritätsendpunkt wie application.properties in der Referenzimplementierung dargestellt: txt 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 Community-Plug-Ins wie Azure Spring Apps oder Micrometer-Integrationen, die Integritätsindikatoren für diese Dienste bereitstellen. Wenn benutzerdefinierte Prüfungen erforderlich sind, können Sie sie implementieren, indem Sie eine benutzerdefinierte HealthIndicator Bohnen 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 (e.g., 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 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. Sie können z. B. Terraform verwenden, um die Integritätsprüfungs-URLs zu verwenden, um die Lebendigkeit und Bereitschaft von Apps zu bestätigen, die für Container-Apps bereitgestellt wurden. Weitere Informationen finden Sie unter Integritätssonden in Container-Apps.

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. Stellen Sie bei der Integration in eine Nachrichtenwarteschlange sicher, dass Sie den Client konfigurieren, der für Interaktionen mit der Warteschlange mit den entsprechenden Wiederholungseinstellungen verantwortlich ist. Geben Sie die Parameter an, z. B. die maximale Anzahl von Wiederholungen, Verzögerung zwischen den Wiederholungen und die maximale Verzögerung.

  • Verwenden Sie das exponentielle Backoff. Implementieren Sie die exponentielle Backoff-Strategie für Wiederholungsversuche. Dies bedeutet, dass die Zeit zwischen jedem Wiederholungsvorgang exponentiell erhöht wird, was dazu beiträgt, die Auslastung des Systems in Zeiten hoher Fehlerraten zu verringern.

  • Verwenden Sie die SDK-Wiederholungsfunktion. 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.

  • Übernehmen Sie Standardresilienzbibliotheken für HTTP-Clients. Für HTTP-Clients können Sie Resilienz4* zusammen mit Spring's RestTemplate oder WebClient verwenden, um Wiederholungen in der HTTP-Kommunikation zu verarbeiten. Die RestTemplate von Spring kann mit der Wiederholungslogik von Resilience4j umschlossen werden, um vorübergehende HTTP-Fehler effektiv zu behandeln.

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

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. Es hilft Ihnen, vertrauliche Informationen wie Verbindungszeichenfolge s in Ihren Code- oder Konfigurationsdateien zu platzieren.

  • 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 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 genau 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, indem Rollen für Containerregistrierung-Push- und Pull-Elemente definiert werden (siehe den folgenden 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 current user access to 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 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 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, z. B. Kubernetes Event-Driven Autoscaler (KEDA) häufig eine präzise Kontrolle, sodass 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 einen Kaltstart zu verhindern, konfigurieren Sie die Einstellungen für die automatische Skalierung, um mindestens ein Replikat beizubehalten. Ein Kaltstart liegt vor, wenn Sie einen Dienst aus einem angehaltenen Zustand initialisieren, was häufig zu einer verzögerten Reaktion führt. Wenn die Minimierung von Kosten eine Priorität ist und Sie Verzögerungen beim Kaltstart tolerieren können, legen Sie beim Konfigurieren der automatischen Skalierung die Mindestreplikatanzahl auf 0 fest.

  • 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 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 jede N-Nachricht 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 mit dem Namen service-bus-queue-length-rulepasst die Anzahl der Dienstreplikate abhängig von der Nachrichtenanzahl in der angegebenen Servicebus-Warteschlange an. Der messageCount Parameter ist auf 10 festgelegt, was bedeutet, dass der Scaler ein Replikat für alle 10 Nachrichten in der Warteschlange hinzufügt. Die maximalen Replikate (max_replicas) werden auf 10 festgelegt, und mindestreplikate sind implizit 0, es sei denn, es wird außer Kraft gesetzt, sodass der Dienst auf Null skaliert werden kann, wenn keine Nachrichten in der Warteschlange vorhanden sind. Die Verbindungszeichenfolge für die Servicebus-Warteschlange wird sicher als geheimer Schlüssel in Azure gespeichert, azure-servicebus-connection-stringder zum Authentifizieren des Scalers beim Service Bus verwendet wird.

    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

Containerisierung bedeutet, dass alle Abhängigkeiten, die für die Funktion der App erforderlich sind, in einem schlanken Image zusammengefasst werden, das zuverlässig auf 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 innerhalb 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. Verwenden Sie beim Erstellen von Docker-Images für Ihre Java-Dienste offizielle OpenJDK-Basisimages. Diese Bilder enthalten nur den minimalen Satz von Paketen, die für die Ausführung von Java erforderlich sind, wodurch sowohl die Paketgröße als auch der Angriffsfläche minimiert werden.

  • Verwenden Sie mehrstufige Dockerfiles. Verwenden Sie eine mehrstufige Dockerfile-Datei, um Buildzeitressourcen vom Laufzeitcontainerimage zu trennen. Es hilft, Ihre Produktionsimages klein und sicher zu halten. 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 nichtroot-Benutzer (über Benutzername oder UID, $APP_UID) aus, um das Prinzip der geringsten Rechte auszurichten. Es beschränkt die potenziellen Auswirkungen eines kompromittierten Containers.

  • Überwachen Sie Port 8080. Wenn Sie als Nicht-Root-Benutzer arbeiten, konfigurieren Sie Ihre Anwendung so, dass sie Port 8080 überwacht. Es ist eine gängige Konvention für Nicht-Root-Benutzer.

  • Kapseln Sie Abhängigkeiten. Stellen Sie sicher, dass alle Abhängigkeiten für die Funktion der App im Docker-Containerimage gekapselt sind. 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 in Container-Apps bereitstellen, müssen Sie Linux-Docker-Images verwenden.

Die Referenzimplementierung veranschaulicht einen Docker-Buildprozess zum Containerisieren einer Java-Anwendung. Diese 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. Volumedeklaration: Ein temporäres Volume (/tmp) ist definiert, sodass temporäre Dateispeicher getrennt vom Hauptdateisystem des Containers gespeichert werden kann.
  2. Kopieren von Artefakten: Die JAR-Datei (email-processor.jar) der Anwendung wird zusammen mit dem Application Insights-Agent (applicationinsights-agent.jar) zur Überwachung in den Container kopiert.
  3. Festlegen des Einstiegspunkts: Der Container ist so konfiguriert, dass die Anwendung mit aktivierter Application Insights-Agent ausgeführt wird, wobei java -javaagent die Anwendung während der Laufzeit überwacht wird.

Mit dieser Dockerfile-Datei bleibt das Image schlanker, indem nur Laufzeitabhängigkeiten eingeschlossen werden, die für Bereitstellungsumgebungen wie Container-Apps geeignet sind, die Linux-basierte Container unterstützen.

# Use 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 entry point 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. Nach der Bereitstellung können Sie Entwurfsmuster simulieren und beobachten.

Diagramm, das die Architektur der Referenzimplementierung zeigt.Abbildung 3: Architektur der Referenzimplementierung: Laden Sie eine Visio-Datei dieser Architektur herunter.