Spring Integration bietet einen Messaging-Mechanismus zum Austausch von Messages
über MessageChannels
. Für die Kommunikation mit externen Systemen werden Kanaladapter verwendet.
In dieser Übung erstellen wir zwei Anwendungen, die über die von Spring Cloud GCP bereitgestellten Spring Integration-Kanaladapter kommunizieren. Mit diesen Adaptern wird Google Cloud Pub/Sub als Back-End für den Nachrichtenaustausch in Spring Integration verwendet.
Außerdem lernen Sie, wie Sie Cloud Shell und den Cloud SDK-Befehl "gcloud" verwenden.
In dieser Anleitung wird Beispielcode aus dem Spring Boot-Startleitfaden verwendet.
Lerninhalte
- Nachrichten zwischen Apps mit Google Cloud Pub/Sub mithilfe von Spring Integration und Spring Cloud GCP austauschen
Voraussetzungen
- Google Cloud Platform-Projekt
- Ein Browser, z. B. Chrome oder Firefox
- Erfahrung mit standardmäßigen Linux-Texteditoren wie Vim, EMACs oder Nano
Wie werden Sie diese Anleitung verwenden?
Wie würden Sie Ihre Erfahrung mit der Entwicklung von HTML/CSS-Web-Apps bewerten?
Wie würden Sie Ihre Erfahrungen mit der Verwendung von Google Cloud Platform-Diensten bewerten?
Einrichtung der Umgebung im eigenen Tempo
Wenn Sie noch kein Google-Konto (Gmail oder Google Apps) haben, müssen Sie eins erstellen. Melden Sie sich in der Google Cloud Platform Console (console.cloud.google.com) an und erstellen Sie ein neues Projekt:
Notieren Sie sich die Projekt-ID, also den projektübergreifend nur einmal vorkommenden Namen eines Google Cloud-Projekts. Der oben angegebene Name ist bereits vergeben und kann leider nicht mehr verwendet werden. Sie wird in diesem Codelab später als PROJECT_ID
bezeichnet.
Als Nächstes müssen Sie die Abrechnung in der Cloud Console aktivieren, um Google Cloud-Ressourcen verwenden zu können.
Dieses Codelab sollte Sie nicht mehr als ein paar Dollar kosten, aber es könnte mehr sein, wenn Sie sich für mehr Ressourcen entscheiden oder wenn Sie sie laufen lassen (siehe Abschnitt „Bereinigen“ am Ende dieses Dokuments).
Neuen Nutzern der Google Cloud Platform steht eine kostenlose Testversion mit einem Guthaben von 300$ zur Verfügung.
Google Cloud Shell
Während Sie Google Cloud von Ihrem Laptop aus per Fernzugriff nutzen können, wird in diesem Codelab Google Cloud Shell verwendet, eine Befehlszeilenumgebung, die in der Cloud ausgeführt wird.
Google Cloud Shell aktivieren
Klicken Sie in der GCP Console oben rechts in der Symbolleiste auf das Cloud Shell-Symbol:
Klicken Sie dann auf "Cloud Shell starten":
Die Bereitstellung und Verbindung mit der Umgebung dauert nur einen Moment:
Diese virtuelle Maschine verfügt über sämtliche Entwicklertools, die Sie benötigen. Sie bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und läuft auf der Google Cloud, wodurch Netzwerkleistung und Authentifizierung deutlich verbessert werden. Sie können die meisten, wenn nicht sogar alle Schritte in diesem Lab einfach mit einem Browser oder Ihrem Google Chromebook durchführen.
Sobald Sie mit Cloud Shell verbunden sind, sollten Sie sehen, dass Sie bereits authentifiziert sind und das Projekt bereits auf Ihre PROJECT_ID eingestellt ist.
Führen Sie in Cloud Shell den folgenden Befehl aus, um zu prüfen, ob Sie authentifiziert sind:
gcloud auth list
Befehlsausgabe
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
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].
Rufen Sie die Seite Google Cloud Pub/Sub-Themen auf und aktivieren Sie die API.
Klicken Sie auf Thema erstellen.
Geben Sie exampleTopic
als Namen des Themas ein und klicken Sie dann auf Erstellen.
Bleiben Sie nach der Erstellung des Themas auf der Seite „Themen“. Suchen Sie nach dem gerade erstellten Thema, klicken Sie auf das Dreipunkt-Menü am Ende der Zeile und wählen Sie Neues Abo aus.
Geben Sie exampleSubscription
in das Textfeld für den Abonnementsnamen ein und klicken Sie auf Erstellen.
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=2.0.6.RELEASE \
-d dependencies=web \
-d baseDir=spring-integration-sender | tar -xzvf -
$ curl https://start.spring.io/starter.tgz \
-d bootVersion=2.0.6.RELEASE \
-d baseDir=spring-integration-receiver | tar -xzvf -
Erstellen wir nun die App zum Senden von Nachrichten. Wechseln Sie in das Verzeichnis der Sende-App.
$ cd spring-integration-sender
Wir möchten, dass unsere App Nachrichten in einen Channel schreibt. Nachdem sich eine Nachricht im Kanal befindet, wird sie vom ausgehenden Kanaladapter abgeholt, 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 aus 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 was passiert mit diesen Nachrichten, nachdem sie im Kanal sind?
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 org.springframework.cloud.gcp.pubsub.core.PubSubTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.cloud.gcp.pubsub.integration.outbound.PubSubMessageHandler;
import org.springframework.messaging.MessageHandler;
@SpringBootApplication
public class DemoApplication {
...
@Bean
@ServiceActivator(inputChannel = "pubsubOutputChannel")
public MessageHandler messageSender(PubSubTemplate pubsubTemplate) {
return new PubSubMessageHandler(pubsubTemplate, "exampleTopic");
}
}
Durch die Anmerkung @ServiceActivator
wird diese MessageHandler
auf alle neuen Nachrichten in inputChannel
angewendet. In diesem Fall rufen wir unseren Ausgangskanaladapter PubSubMessageHandler
auf, um die Nachricht im exampleTopic
-Thema von Google Cloud Pub/Sub zu veröffentlichen.
Nachdem der Kanaladapter eingerichtet ist, können wir jetzt ein PubsubOutboundGateway
-Objekt automatisch einbinden 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("/");
}
}
Dank der Annotation @PostMapping
haben wir jetzt einen Endpunkt, der auf HTTP-POST-Anfragen wartet. Dazu muss jedoch auch der Klasse DemoApplication
die Annotation @RestController
hinzugefügt werden, 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 {
...
}
Damit die App ausgeführt werden kann, müssen wir nur die erforderlichen Abhängigkeiten hinzufügen.
pom.xml
<project>
...
<!-- Add Spring Cloud GCP Dependency BOM -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-dependencies</artifactId>
<version>1.0.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
...
<!-- Add Pub/Sub Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
</dependency>
<!-- Add Spring Integration -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
</dependencies>
</project>
Führen Sie die Sender-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 überwacht Port 8080 und den Endpunkt /postMessage
auf POST-Anfragen mit einer Nachricht. Darauf gehen wir später noch ein.
Wir haben gerade eine App erstellt, die Nachrichten über Google Cloud Pub/Sub sendet. Als Nächstes erstellen wir eine weitere App, die diese Nachrichten empfängt und verarbeitet.
Klicken Sie auf +, um eine neue Cloud Shell-Sitzung zu öffnen.
Wechseln Sie dann in der neuen Cloud Shell-Sitzung in das Verzeichnis der Empfänger-App:
$ cd spring-integration-receiver
In der vorherigen App wurde durch die Deklaration des Messaging-Gateways der ausgehende Channel für uns erstellt. Da wir kein Messaging-Gateway zum Empfangen von Nachrichten verwenden, müssen wir unseren eigenen MessageChannel
deklarieren, an dem eingehende Nachrichten eingehen.
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 org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.gcp.pubsub.core.PubSubTemplate;
import org.springframework.cloud.gcp.pubsub.integration.inbound.PubSubInboundChannelAdapter;
@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 gepostet werden. Was sollen wir mit diesen Nachrichten tun?
Lassen Sie uns sie mit einem @ServiceActivator
verarbeiten, der ausgelöst wird, wenn neue Nachrichten bei pubsubInputChannel
eingehen.
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);
}
}
In diesem Fall protokollieren wir nur die Nutzlast der Nachricht.
Wir müssen die erforderlichen Abhängigkeiten hinzufügen.
pom.xml
<project>
...
<!-- Add Spring Cloud GCP Dependency BOM -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-dependencies</artifactId>
<version>1.0.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
...
<!-- Add Pub/Sub Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
</dependency>
<!-- Add Spring Integration -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
</dependencies>
</project>
Führen Sie die Empfänger-App aus.
$ ./mvnw spring-boot:run
Alle Nachrichten, die Sie an die Sender-App senden, werden nun in der Empfänger-App protokolliert. Öffnen Sie dazu eine neue Cloud Shell-Sitzung und senden Sie eine HTTP-POST-Anfrage an die Sender-App.
$ curl --data "message=Hello world!" localhost:8080/postMessage
Prüfe dann, ob die Empfänger-App die von dir gesendete Nachricht protokolliert hat.
INFO: Message arrived! Payload: Hello world!
Löschen Sie das Abo und das Thema, die im Rahmen dieser Übung erstellt wurden.
$ gcloud beta pubsub subscriptions delete exampleSubscription
$ gcloud beta pubsub topics delete exampleTopic
Sie richten zwei Spring Boot-Apps ein, 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.
Sie haben gelernt, wie Sie die Spring Integration Channel Adapters für Google Cloud Pub/Sub verwenden.
Weitere Informationen
- Google Cloud Pub/Sub: https://cloud.google.com/pubsub/
- Spring on GCP-Projekt: http://cloud.spring.io/spring-cloud-gcp/
- GitHub-Repository für Spring on GCP: https://github.com/spring-cloud/spring-cloud-gcp
- Java auf der Google Cloud Platform: https://cloud.google.com/java/
Lizenz
Dieser Text ist mit einer Creative Commons Attribution 2.0 Generic License lizenziert.