Java >> Java Tutorial >  >> Java

Erstellen von Microservices mit ereignisgesteuerter Architektur

In diesem Beitrag werden wir erörtern, wie wir Microservices mit ereignisgesteuerter Architektur erstellen können. Im Rahmen des Beitrags werde ich auch ein Beispiel für einen ereignisgesteuerten Microservice zeigen. Wenn Sie nicht wissen, was ein Microservice ist, können Sie hier mit meiner Einführung beginnen.

Microservices – Ereignisgesteuerte Architektur

Traditionell würden wir einen REST-basierten Microservice verwenden. Bei diesem Microservice würde ein Client Daten anfordern und der Server würde dann mit den Daten antworten. Aber es gab Nachteile darin, dass der Client warten musste, bis der Server antwortet. Ein Server kann ausgefallen sein oder andere Anfragen bedienen, während er gerade dabei ist, die Antwort auf die aktuellen Client-Anfragen zu verzögern.

Kurz gesagt, wenn ein System aufgrund synchronisierter Verbindungen langsam wird, können wir eine ereignisgesteuerte Architektur verwenden, um das System asynchron zu machen.

Event-Drive-Microservices verwenden einen schlussendlich konsistenten Ansatz. Jeder Dienst veröffentlicht Ereignisdaten, wann immer es eine Aktualisierung oder Transaktion gibt. Andere Dienste abonnieren diese Dienstveröffentlichungsereignisse. Wenn diese abonnierten Dienste ein Ereignis erhalten, aktualisieren sie ihre Daten.

Ein einfaches Beispiel für diesen Ansatz:Wenn ein Kunde eine Geschenkkarte einlöst, wird ein einziges Einlösungsereignis erstellt und von verschiedenen Diensten genutzt.

  1. Ein Prämiendienst, der einen Einlösungsdatensatz in die Datenbank schreiben kann
  2. Ein Kunde erhält einen Artikel, der über eine Geschenkkarte gekauft wurde
  3. Ein Partnerdienst, der die Geschenkkarte verifiziert und die Einlösung und entsprechende Bearbeitung des vom Kunden gekauften Artikels ermöglicht.

Die ereignisgesteuerte Architektur erfolgt entweder über Warteschlangen oder das Pub-Sub-Modell. Im Pub/Sub-Modell veröffentlicht ein Dienst das Ereignis und abonnierte Dienste nutzen dieses Ereignis. Es unterscheidet sich nicht wesentlich von dem, was Warteschlangen und Themen tun.

Vorteile der ereignisgesteuerten Architektur

  • Lose Kupplung – Dienste müssen nicht von anderen Diensten abhängen. Da die Architektur reaktiv ist, können Dienste voneinander unabhängig sein.
  • Asynchron – Ein Verlagsdienst veröffentlicht die Veranstaltung. Ein abonnierender Dienst kann das Ereignis nutzen, wann immer es zur Nutzung bereit ist. Der Hauptvorteil der asynchronen Architektur besteht darin, dass Dienste keine Ressourcen blockieren.
  • Skalierung – Da die Dienste unabhängig sind, führen die meisten Dienste eine einzelne Aufgabe aus. Es wird auch einfacher zu skalieren, um Engpässe zu finden.

Nachteile der ereignisgesteuerten Architektur

Jedes Design ist ein Kompromiss. Wir haben kein perfektes Design in verteilten Systemen. Mit einer ereignisgesteuerten Architektur kann man die Lösung leicht überkonstruieren, indem man Bedenken trennt.

Ereignisgesteuerte Architektur erfordert Vorabinvestitionen. Da die Daten nicht unbedingt sofort verfügbar sind, kann dies zu Bedenken bei Transaktionen führen. Eventuelle Konsistenz kann schwer zu untersuchen sein, wenn es Probleme mit Daten gibt. Es kann zu doppelten Ereignissen kommen, die zu doppelten Daten führen. Ereignisgesteuerte Modelle unterstützen keine ACID-Transaktionen.

Framework für Architektur

Ungeachtet dieser Nachteile ist die ereignisgesteuerte Architektur schnell und liefert erfolgreiche Ergebnisse. Daher stellt sich die nächste Frage, welches Framework zum Erstellen dieser Architektur gewählt werden soll. Derzeit gibt es zwei Möglichkeiten

  • Nachrichtenverarbeitung
  • Stream-Verarbeitung

Nachrichtenverarbeitung

Bei der Nachrichtenverarbeitung erstellt ein Dienst eine Nachricht und sendet sie an das Ziel. Ein abonnierender Dienst nimmt die Nachricht von diesem Ziel auf. In AWS verwenden wir SNS (Simple Notification Service) und SQS (Simple Queue Service). Ein Dienst sendet eine Nachricht an ein Thema und eine Warteschlange, die dieses Thema abonniert, nimmt diese Nachricht auf und verarbeitet sie weiter.

SNS und SQS sind nicht die einzigen Frameworks da draußen. Nachrichtenwarteschlangen verwenden ein Speicher- und Weiterleitungssystem von Brokern, bei dem Ereignisse von Broker zu Broker übertragen werden. ActiveMQ und RabbitMQ sind die anderen beiden Beispiele für Nachrichtenwarteschlangen

Stream-Verarbeitung

Bei der Stream-Verarbeitung sendet ein Dienst ein Ereignis und der abonnierte Dienst nimmt dieses Ereignis auf. Trotzdem sind Ereignisse nicht für ein bestimmtes Ziel bestimmt.

Normalerweise gibt ein Erzeuger von Ereignissen Ereignisse aus und kann sie im Speicher speichern. Ein Konsument von Ereignissen kann diese Ereignisse aus dem Datenspeicher konsumieren. Das beliebteste Framework für die Stream-Verarbeitung ist Kafka. Im Grunde folgt es einem Pub-Sub-Modell.

Stream-Prozessoren (wie Kafka) bieten vor allem die Beständigkeit von Daten. Daten gehen nicht verloren und wenn das System offline geht, kann es den Verlauf der Ereignisse reproduzieren.

Demo eines auf einer ereignisgesteuerten Architektur basierenden Microservices

Als Teil dieser Demo implementieren wir eine Spring Boot-Anwendung zusammen mit dem ActiveMQ-Message-Broker-Dienst.

ActiveMQ-Nachrichtendienst

ActiveMQ ist ein Open-Source-Nachrichtenbroker. Derzeit unterstützt es Clients, die in Java, Python, .Net, C++ und mehr geschrieben wurden.

Laden Sie ActiveMQ hier herunter. Sobald Sie den heruntergeladenen Ordner auf Ihrem Computer entpackt haben, können Sie zu bin gehen Verzeichnis, um den ActiveMQ-Server mit einem Befehl activemq.bat start zu starten . Dadurch wird der ActiveMQ-Server bei http://localhost:8161 gestartet .

Sender-Anwendung mit Spring Boot

Lassen Sie uns nun eine Message Sender-Anwendung mit Spring Boot erstellen. Wir benötigen die folgenden Abhängigkeiten


dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-activemq'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

Wir werden die JMS-Konfiguration hinzufügen, um eine ActiveMQ-Warteschlange zu erstellen.


@Configuration
public class JmsConfig
{
    @Bean
    public Queue queue()
    {
        return new ActiveMQQueue("demo-queue");
    }
}

Dies erstellt eine Bean für unsere Warteschlange demo-queue . Um Nachrichten über unsere Senderanwendung an diese Warteschlange zu senden, erstellen wir wie folgt eine REST-API:


@RestController
@RequestMapping("/v1/betterjavacode/api")
public class MessageController
{
    @Autowired
    private Queue queue;

    @Autowired
    private JmsTemplate jmsTemplate;

    @GetMapping("/message/")
    public ResponseEntity sendMessage(@RequestBody String message)
    {
        jmsTemplate.convertAndSend(queue, message);
        return new ResponseEntity(message, HttpStatus.OK);
    }

}

Anschließend haben wir queue eingefügt und jmsTemplate Beans in unserem RestController, damit wir die Nachricht senden können.

Andererseits haben wir auch eine Empfängeranwendung, bei der es sich um einen Zieldienst oder Verbraucherdienst handelt, der die Nachricht von der Senderanwendung verarbeitet.

Erstellen Sie eine Nachrichtenkonsumentenklasse in unserer Empfängeranwendung


@Component
@EnableJms
public class MessageConsumer
{
    private final Logger logger = LoggerFactory.getLogger(MessageConsumer.class);

    @JmsListener(destination = "demo-queue")
    public void receiveMessage(String message)
    {
        // TO-DO
        logger.info("Received a message = {}", message);
    }
}

Die Anmerkung von @JmsListener with destination bewirkt, dass die Anwendung auf diese Warteschlange lauscht. @EnableJms aktiviert die Anmerkung @JmsListener .

Wir müssen noch ActiveMQ-Eigenschaften hinzufügen, damit beide Anwendungen wissen, wo der ActiveMQ-Server läuft. Fügen Sie also die folgenden Eigenschaften zu application.properties hinzu


spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin

Starten Sie nun beide Spring Boot-Anwendungen. Die Senderanwendung läuft auf 8080 und die Empfängeranwendung auf 8081.

Wenn wir nun die Protokolle der Empfängeranwendung überprüfen, sehen wir, dass sie diese Nachricht aus der ActiveMQ-Warteschlange demo-queue verarbeitet hat .

Wir können auch den Status der Warteschlange auf dem ActiveMQ-Server sehen.

Hier können Sie sehen, dass die Warteschlange zwei Nachrichten vom Absender empfangen und an den Verbraucher übermittelt hat. Der Code für diese Demo ist in meinem Github-Repository verfügbar.

Schlussfolgerung

In diesem Beitrag habe ich die ereignisgesteuerte Architektur für Microservices besprochen. Wir haben auch die Vor- und Nachteile dieser Architektur diskutiert. Schließlich haben wir gezeigt, wie wir ActiveMQ verwenden können, um einen ereignisgesteuerten, architekturbasierten Microservice für asynchrone Kommunikation einzurichten.

Übrigens, wenn Sie mein Buch für Spring Security noch nicht gekauft haben, können Sie es hier kaufen ODER Sie können hier mehr darüber lesen.

Referenzen

Ereignisgesteuerte Microservices mit ActiveMQ – ActiveMQ


Java-Tag