Messaging mit Spring Integration und Google Cloud Pub/Sub

1. Übersicht

Spring Integration bietet einen Messaging-Mechanismus zum Austausch von Messages über MessageChannels. Kanaladapter werden verwendet, um mit externen Systemen zu kommunizieren.

In dieser Übung erstellen wir zwei Apps, die über die von Spring Cloud GCP bereitgestellten Spring Integration-Kanaladapter kommunizieren. Mit diesen Adaptern verwendet Spring Integration Google Cloud Pub/Sub als Backend für den Nachrichtenaustausch.

Außerdem lernen Sie, wie Sie Cloud Shell und den Cloud SDK-Befehl `gcloud` verwenden.

In dieser Anleitung wird Beispielcode aus dem Startleitfaden zu Spring Boot verwendet.

Lerninhalte

  • Nachrichten zwischen Apps mit Google Cloud Pub/Sub über Spring Integration und Spring Cloud GCP austauschen

Voraussetzungen

  • Google Cloud Platform-Projekt
  • Browser, z. B. Chrome oder Firefox
  • Erfahrung mit standardmäßigen Linux-Texteditoren wie Vim, EMACs oder Nano

Wie möchten Sie diese Anleitung verwenden?

Nur lesen Lesen und Übungen ausführen

Wie würden Sie Ihre Erfahrung mit der Entwicklung von HTML/CSS-Webanwendungen bewerten?

Anfänger Fortgeschritten Experte

Wie würden Sie Ihre Erfahrung mit der Verwendung von Google Cloud Platform-Diensten bewerten?

Anfänger Fortgeschritten Experte

2. Einrichtung und Anforderungen

Umgebung zum selbstbestimmten Lernen einrichten

  1. Melden Sie sich in der Google Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes. Wenn Sie noch kein Gmail- oder Google Workspace-Konto haben, müssen Sie eines erstellen.

b35bf95b8bf3d5d8.pnga99b7ace416376c4.pngbd84a6d3004737c5.png

  • Der Projektname ist der Anzeigename für die Teilnehmer dieses Projekts. Er ist ein String, der von Google APIs nicht verwendet wird. Sie können ihn jederzeit aktualisieren.
  • Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und unveränderlich. Sie kann also nicht geändert werden, nachdem sie festgelegt wurde. Die Cloud Console generiert automatisch einen eindeutigen String. In der Regel ist es nicht wichtig, wie dieser String aussieht. In den meisten Codelabs müssen Sie auf Ihre Projekt-ID verweisen (in der Regel als PROJECT_ID angegeben). Wenn Ihnen die generierte ID nicht gefällt, können Sie eine andere zufällige ID generieren. Alternativ können Sie eine eigene ID verwenden und prüfen, ob sie verfügbar ist. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts bestehen.
  • Zur Information: Es gibt einen dritten Wert, die Projektnummer, die von einigen APIs verwendet wird. Weitere Informationen zu diesen drei Werten finden Sie in der Dokumentation.
  1. Als Nächstes müssen Sie die Abrechnung in der Cloud Console aktivieren, um Cloud-Ressourcen/APIs zu verwenden. Die Ausführung dieses Codelabs kostet wenig oder gar nichts. Wenn Sie Ressourcen herunterfahren möchten, um zu vermeiden, dass Ihnen nach Abschluss dieser Anleitung Kosten in Rechnung gestellt werden, können Sie die erstellten Ressourcen oder das Projekt löschen. Neue Google Cloud-Nutzer können das kostenlose Testprogramm im Wert von 300 $ nutzen.

Google Cloud Shell

Google Cloud kann zwar von Ihrem Laptop aus per Fernzugriff genutzt werden, in diesem Codelab verwenden wir jedoch Google Cloud Shell, eine Befehlszeilenumgebung, die in der Cloud ausgeführt wird.

Cloud Shell aktivieren

  1. Klicken Sie in der Cloud Console auf Cloud Shell aktivieren 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Wenn Sie Cloud Shell zum ersten Mal starten, wird ein Fenster mit einer Beschreibung eingeblendet. Klicken Sie in diesem Fall einfach auf Weiter.

9c92662c6a846a5c.png

Das Herstellen der Verbindung mit der Cloud Shell sollte nur wenige Augenblicke dauern.

9f0e51b578fecce5.png

Auf dieser virtuellen Maschine sind alle erforderlichen Entwicklungstools installiert. Sie bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und wird in Google Cloud ausgeführt, was die Netzwerkleistung und Authentifizierung erheblich verbessert. Die meisten, wenn nicht alle Aufgaben in diesem Codelab können mit einem Browser ausgeführt werden.

Sobald die Verbindung mit der Cloud Shell hergestellt ist, sehen Sie, dass Sie authentifiziert sind und für das Projekt schon Ihre Projekt-ID eingestellt ist.

  1. Führen Sie in der Cloud Shell den folgenden Befehl aus, um zu prüfen, ob Sie authentifiziert sind:
gcloud auth list

Befehlsausgabe

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Führen Sie in der Cloud Shell den folgenden Befehl aus, um zu prüfen, ob der Befehl `gcloud` Ihr Projekt kennt:
gcloud config list project

Befehlsausgabe

[core]
project = <PROJECT_ID>

Ist dies nicht der Fall, können Sie die Einstellung mit diesem Befehl vornehmen:

gcloud config set project <PROJECT_ID>

Befehlsausgabe

Updated property [core/project].

3. Pub/Sub-Ressourcen bereitstellen

Rufen Sie die Seite „Google Cloud Pub/Sub-Themen“ auf.

Klicken Sie auf Thema erstellen.

4c938409dc7169a6.png

Geben Sie exampleTopic als Namen des Themas ein und klicken Sie dann auf Erstellen.

e2daeec91537f672.png

Bleiben Sie nach dem Erstellen des Themas auf der Seite „Themen“. Suchen Sie das gerade erstellte Thema, klicken Sie auf die drei vertikalen Punkte am Ende der Zeile und dann auf Neues Abo.

975efa26e5054936.png

Geben Sie exampleSubscription in das Textfeld für den Abo-Namen ein und klicken Sie auf Erstellen.

f7a91d9e1cb48009.png

4. Spring Boot-Anwendungen initialisieren

Nachdem Cloud Shell gestartet wurde, können Sie über die Befehlszeile mit Spring Initializr zwei neue Spring Boot-Anwendungen generieren:

$ curl https://start.spring.io/starter.tgz \
  -d bootVersion=3.0.5 \
  -d dependencies=web,integration,cloud-gcp-pubsub \
  -d type=maven-project \
  -d baseDir=spring-integration-sender | tar -xzvf -

$ curl https://start.spring.io/starter.tgz \
  -d bootVersion=3.0.5 \
  -d dependencies=web,integration,cloud-gcp-pubsub \
  -d type=maven-project \
  -d baseDir=spring-integration-receiver | tar -xzvf -

5. Anwendung zum Senden von Nachrichten erstellen

Erstellen wir nun unsere App zum Senden von Nachrichten. Wechseln Sie zum Verzeichnis der Sende-App.

$ cd spring-integration-sender

Wir möchten, dass unsere App Nachrichten in einen Kanal schreibt. Sobald sich eine Nachricht im Kanal befindet, wird sie vom Ausgangskanaladapter abgerufen, der sie von einer generischen Spring-Nachricht in eine Google Cloud Pub/Sub-Nachricht konvertiert und in einem Google Cloud Pub/Sub-Thema veröffentlicht.

Damit unsere App in einen Kanal schreiben kann, können wir ein Spring Integration-Messaging-Gateway verwenden. Deklarieren Sie mit einem Texteditor wie vim, emacs oder nano eine PubsubOutboundGateway-Schnittstelle in der Klasse DemoApplication.

src/main/java/com/example/demo/DemoApplication.java

...
import org.springframework.integration.annotation.MessagingGateway;

@SpringBootApplication
public class DemoApplication {

  ...

  @MessagingGateway(defaultRequestChannel = "pubsubOutputChannel")
  public interface PubsubOutboundGateway {
    void sendToPubsub(String text);
  }
}

Wir haben jetzt einen Mechanismus zum Senden von Nachrichten an einen Kanal. Aber wohin werden diese Nachrichten gesendet, nachdem sie sich im Kanal befinden?

Wir benötigen einen Ausgangskanaladapter, um neue Nachrichten im Kanal zu verarbeiten und in einem Google Cloud Pub/Sub-Thema zu veröffentlichen.

src/main/java/com/example/demo/DemoApplication.java

...
import com.google.cloud.spring.pubsub.core.PubSubTemplate;
import com.google.cloud.spring.pubsub.integration.outbound.PubSubMessageHandler;

import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.MessageHandler;

@SpringBootApplication
public class DemoApplication {

  ...

  @Bean
  @ServiceActivator(inputChannel = "pubsubOutputChannel")
  public MessageHandler messageSender(PubSubTemplate pubsubTemplate) {
    return new PubSubMessageHandler(pubsubTemplate, "exampleTopic");
  }
}

Die Annotation @ServiceActivator bewirkt, dass dieser MessageHandler auf alle neuen Nachrichten in inputChannel angewendet wird. In diesem Fall rufen wir unseren Ausgangskanaladapter PubSubMessageHandler auf, um die Nachricht im Thema exampleTopic von Google Cloud Pub/Sub zu veröffentlichen.

Nachdem der Kanaladapter eingerichtet ist, können wir jetzt ein PubsubOutboundGateway-Objekt automatisch verknüpfen und damit eine Nachricht in einen Kanal schreiben.

src/main/java/com/example/demo/DemoApplication.java

...
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.view.RedirectView;

@SpringBootApplication
public class DemoApplication {

  ...

  @Autowired
  private PubsubOutboundGateway messagingGateway;

  @PostMapping("/postMessage")
  public RedirectView postMessage(@RequestParam("message") String message) {
    this.messagingGateway.sendToPubsub(message);
    return new RedirectView("/");
  }
}

Aufgrund der Annotation @PostMapping haben wir jetzt einen Endpunkt, der auf HTTP-POST-Anfragen wartet. Dazu müssen wir jedoch auch der Klasse DemoApplication die Annotation @RestController hinzufügen, um sie als REST-Controller zu kennzeichnen.

src/main/java/com/example/demo/DemoApplication.java

import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication {
  ...
}

Prüfen Sie, ob JAVA_HOME auf die richtige Version festgelegt ist.

export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64

Führen Sie die Sende-App aus.

# Set the Project ID in environmental variable
$ export GOOGLE_CLOUD_PROJECT=`gcloud config list --format 'value(core.project)'`

$ ./mvnw spring-boot:run

Die App wartet auf POST-Anfragen mit einer Nachricht auf Port 8080 und Endpunkt /postMessage. Darauf kommen wir später zurück.

6. Anwendung zum Empfangen von Nachrichten erstellen

Wir haben gerade eine App erstellt, die Nachrichten über Google Cloud Pub/Sub sendet. Jetzt erstellen wir eine weitere App, die diese Nachrichten empfängt und verarbeitet.

Klicken Sie auf + , um eine neue Cloud Shell-Sitzung zu öffnen.

9799bee5fea95aa6.png

Wechseln Sie dann in der neuen Cloud Shell-Sitzung zum Verzeichnis der Empfänger-App:

$ cd spring-integration-receiver

In der vorherigen App wurde durch die Deklaration des Messaging-Gateways der Ausgangskanal für uns erstellt. Da wir kein Messaging-Gateway zum Empfangen von Nachrichten verwenden, müssen wir einen eigenen MessageChannel deklarieren, in dem eingehende Nachrichten ankommen.

src/main/java/com/example/demo/DemoApplication.java

...
import org.springframework.context.annotation.Bean;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.messaging.MessageChannel;

@SpringBootApplication
public class DemoApplication {

  ...

  @Bean
  public MessageChannel pubsubInputChannel() {
    return new DirectChannel();
  }
}

Wir benötigen den Eingangskanaladapter, um Nachrichten von Google Cloud Pub/Sub zu empfangen und an pubsubInputChannel weiterzuleiten.

src/main/java/com/example/demo/DemoApplication.java

...
import com.google.cloud.spring.pubsub.core.PubSubTemplate;
import com.google.cloud.spring.pubsub.integration.inbound.PubSubInboundChannelAdapter;

import org.springframework.beans.factory.annotation.Qualifier;

@SpringBootApplication
public class DemoApplication {

  ...

  @Bean
  public PubSubInboundChannelAdapter messageChannelAdapter(
      @Qualifier("pubsubInputChannel") MessageChannel inputChannel,
      PubSubTemplate pubSubTemplate) {
    PubSubInboundChannelAdapter adapter =
        new PubSubInboundChannelAdapter(pubSubTemplate, "exampleSubscription");
    adapter.setOutputChannel(inputChannel);

    return adapter;
  }
}

Dieser Adapter wird an pubsubInputChannel gebunden und wartet auf neue Nachrichten aus dem Google Cloud Pub/Sub-Abo exampleSubscription.

Wir haben einen Kanal, in dem eingehende Nachrichten veröffentlicht werden. Aber was sollen wir mit diesen Nachrichten tun?

Wir verarbeiten sie mit einem @ServiceActivator, der ausgelöst wird, wenn neue Nachrichten in pubsubInputChannel eingehen. In diesem Fall protokollieren wir nur die Nutzlast der Nachricht.

src/main/java/com/example/demo/DemoApplication.java

...
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.integration.annotation.ServiceActivator;

@SpringBootApplication
public class DemoApplication {

  ...

  private static final Log LOGGER = LogFactory.getLog(DemoApplication.class);

  @ServiceActivator(inputChannel = "pubsubInputChannel")
  public void messageReceiver(String payload) {
    LOGGER.info("Message arrived! Payload: " + payload);
  }
}

Prüfen Sie, ob JAVA_HOME auf die richtige Version festgelegt ist.

export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64

Führen Sie die Empfänger-App aus.

$ ./mvnw spring-boot:run -Dspring-boot.run.jvmArguments="-Dserver.port=8081"

Alle Nachrichten, die Sie an die Sende-App senden, werden jetzt in der Empfänger-App protokolliert. Öffnen Sie dazu eine neue Cloud Shell-Sitzung und senden Sie eine HTTP-POST-Anfrage an die Sende-App.

$ curl --data "message=Hello world!" localhost:8080/postMessage

Prüfen Sie dann, ob die Empfänger-App die von Ihnen gesendete Nachricht protokolliert hat.

INFO: Message arrived! Payload: Hello world!

7. Bereinigen

Löschen Sie das Abo und das Thema, die im Rahmen dieser Übung erstellt wurden.

$ gcloud pubsub subscriptions delete exampleSubscription
$ gcloud pubsub topics delete exampleTopic

8. Zusammenfassung

Sie haben zwei Spring Boot-Apps eingerichtet, die die Spring Integration-Kanaladapter für Google Cloud Pub/Sub verwenden. Sie tauschen Nachrichten untereinander aus, ohne jemals mit der Google Cloud Pub/Sub API zu interagieren.

9. Glückwunsch!

Sie haben gelernt, wie Sie die Spring Integration-Kanaladapter für Google Cloud Pub/Sub verwenden.

Weitere Informationen

Lizenz

Dieser Text ist mit einer Creative Commons Attribution 2.0 Generic License lizenziert.