Spring Integration fornisce un meccanismo di messaggistica per scambiare Messages
tramite MessageChannels
. Utilizza gli adattatori di canale per comunicare con sistemi esterni.
In questo esercizio creeremo due app che comunicano utilizzando gli adattatori del canale Spring Integration forniti da Spring Cloud GCP. Questi adattatori consentono a Spring Integration di utilizzare Google Cloud Pub/Sub come backend di scambio di messaggi.
Imparerai a utilizzare Cloud Shell e il comando gcloud di Cloud SDK.
Questo tutorial utilizza il codice di esempio della guida introduttiva a Spring Boot.
Cosa imparerai a fare
- Come scambiare messaggi tra app con Google Cloud Pub/Sub utilizzando Spring Integration e Spring Cloud GCP
Che cosa ti serve
- Un progetto Google Cloud
- Un browser, ad esempio Chrome o Firefox
- Familiarità con gli editor di testo standard di Linux, ad esempio Vim, EMAC o Nano
Come utilizzerai questo tutorial?
Come valuti la tua esperienza di creazione di app web HTML/CSS?
Come valuti la tua esperienza di utilizzo dei servizi Google Cloud Platform?
Configurazione dell'ambiente autonoma
Se non hai ancora un Account Google (Gmail o Google Apps), devi crearne uno. Accedi alla console di Google Cloud (console.cloud.google.com) e crea un nuovo progetto:
Ricorda l'ID progetto, un nome univoco per tutti i progetti Google Cloud (il nome riportato sopra è già stato utilizzato e non funzionerà per te, mi dispiace). In questo codelab verrà chiamato PROJECT_ID
.
Successivamente, dovrai abilitare la fatturazione nella console Cloud per utilizzare le risorse Google Cloud.
L'esecuzione di questo codelab non dovrebbe costarti più di qualche dollaro, ma potrebbe essere più cara se decidi di utilizzare più risorse o se le lasci in esecuzione (vedi la sezione "Pulizia" alla fine di questo documento).
I nuovi utenti di Google Cloud Platform possono beneficiare di una prova senza costi di 300$.
Google Cloud Shell
Anche se Google Cloud può essere utilizzato da remoto dal tuo laptop, in questo codelab utilizzeremo Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.
Attiva Google Cloud Shell
Nella console GCP, fai clic sull'icona di Cloud Shell nella barra degli strumenti in alto a destra:
Poi fai clic su "Avvia Cloud Shell":
Bastano pochi istanti per eseguire il provisioning e connettersi all'ambiente:
Questa macchina virtuale è caricata con tutti gli strumenti di sviluppo di cui avrai bisogno. Offre una home directory permanente da 5 GB e viene eseguita su Google Cloud, migliorando notevolmente le prestazioni di rete e l'autenticazione. Gran parte, se non tutto, il lavoro in questo lab può essere svolgersi semplicemente con un browser o con Google Chromebook.
Una volta eseguita la connessione a Cloud Shell, dovresti vedere che il tuo account è già autenticato e il progetto è già impostato sul tuo PROJECT_ID.
Esegui questo comando in Cloud Shell per verificare che l'account sia autenticato:
gcloud auth list
Output comando
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Output comando
[core] project = <PROJECT_ID>
In caso contrario, puoi impostarlo con questo comando:
gcloud config set project <PROJECT_ID>
Output comando
Updated property [core/project].
Vai alla pagina degli argomenti di Google Cloud Pub/Sub e abilita l'API.
Fai clic su Crea argomento.
Digita exampleTopic
come nome dell'argomento e fai clic su Crea.
Dopo aver creato l'argomento, rimani nella pagina Argomenti. Cerca l'argomento che hai appena creato, premi i tre puntini verticali alla fine della riga e fai clic su Nuova sottoscrizione.
Digita exampleSubscription
nella casella di testo del nome dell'abbonamento e fai clic su Crea.
Dopo l'avvio di Cloud Shell, puoi utilizzare la riga di comando per generare due nuove applicazioni Spring Boot con Spring Initializr:
$ 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 -
Ora creiamo la nostra app di invio di messaggi. Passa alla directory dell'app di invio.
$ cd spring-integration-sender
Vogliamo che la nostra app scriva messaggi su un canale. Una volta che un messaggio si trova nel canale, viene prelevato dall'adattatore del canale in uscita, che lo converte da un messaggio Spring generico a un messaggio Google Cloud Pub/Sub e lo pubblica in un argomento Google Cloud Pub/Sub.
Affinché la nostra app possa scrivere su un canale, possiamo utilizzare un gateway di messaggistica Spring Integration. Utilizzando un editor di testo di vim
, emacs
o nano
, dichiara un'interfaccia PubsubOutboundGateway
all'interno della classe 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);
}
}
Ora abbiamo un meccanismo per inviare messaggi a un canale, ma dove vanno a finire questi messaggi una volta inviati?
Abbiamo bisogno di un adattatore del canale in uscita per utilizzare i nuovi messaggi nel canale e pubblicarli in un argomento Google Cloud Pub/Sub.
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");
}
}
L'annotazione @ServiceActivator
fa sì che MessageHandler
venga applicato a tutti i nuovi messaggi in inputChannel
. In questo caso, chiamiamo il nostro adattatore del canale in uscita, PubSubMessageHandler
, per pubblicare il messaggio nell'argomento exampleTopic
di Google Cloud Pub/Sub.
Con l'adattatore del canale in posizione, ora possiamo collegare automaticamente un oggetto PubsubOutboundGateway
e utilizzarlo per scrivere un messaggio a un canale.
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("/");
}
}
Grazie all'annotazione @PostMapping
, ora abbiamo un endpoint che è in ascolto delle richieste POST HTTP, ma non senza aggiungere anche un'annotazione @RestController
alla classe DemoApplication
per contrassegnarla come controller REST.
src/main/java/com/example/demo/DemoApplication.java
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class DemoApplication {
...
}
Per eseguire l'app, dobbiamo solo aggiungere le dipendenze richieste.
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>
Esegui l'app mittente.
# Set the Project ID in environmental variable
$ export GOOGLE_CLOUD_PROJECT=`gcloud config list \
--format 'value(core.project)'`
$ ./mvnw spring-boot:run
L'app è in ascolto delle richieste POST contenenti un messaggio sulla porta 8080 e sull'endpoint /postMessage
, ma ci arriveremo più avanti.
Abbiamo appena creato un'app che invia messaggi tramite Google Cloud Pub/Sub. Ora creeremo un'altra app che riceve questi messaggi e li elabora.
Fai clic su + per aprire una nuova sessione di Cloud Shell.
Quindi, nella nuova sessione di Cloud Shell, cambia directory con quella dell'app ricevitore:
$ cd spring-integration-receiver
Nell'app precedente, la dichiarazione del gateway di messaggistica creava il canale in uscita per noi. Poiché non utilizziamo un gateway di messaggistica per ricevere i messaggi, dobbiamo dichiarare il nostro MessageChannel
in cui arriveranno i messaggi in entrata.
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();
}
}
Avremo bisogno dell'adattatore del canale in entrata per ricevere messaggi da Google Cloud Pub/Sub e inoltrarli a pubsubInputChannel
.
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;
}
}
Questo adattatore si associa a pubsubInputChannel
e rimane in ascolto dei nuovi messaggi dalla sottoscrizione exampleSubscription
di Google Cloud Pub/Sub.
Abbiamo un canale in cui vengono pubblicati i messaggi in arrivo, ma cosa farne?
Elaboriamoli con un @ServiceActivator
che viene attivato quando arrivano nuovi messaggi all'indirizzo pubsubInputChannel
.
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 questo caso, registreremo solo il payload del messaggio.
Dobbiamo aggiungere le dipendenze necessarie.
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>
Esegui l'app ricevitore.
$ ./mvnw spring-boot:run
Ora tutti i messaggi che invii all'app mittente verranno registrati nell'app destinatario. Per verificare, apri una nuova sessione di Cloud Shell ed esegui una richiesta HTTP POST all'app mittente.
$ curl --data "message=Hello world!" localhost:8080/postMessage
Dopodiché, verifica che l'app del destinatario abbia registrato il messaggio che hai inviato.
INFO: Message arrived! Payload: Hello world!
Elimina la sottoscrizione e l'argomento creati nell'ambito di questo esercizio.
$ gcloud beta pubsub subscriptions delete exampleSubscription
$ gcloud beta pubsub topics delete exampleTopic
Configuri due app Spring Boot che utilizzano gli adattatori del canale Spring Integration per Google Cloud Pub/Sub. Si scambiano messaggi tra loro senza mai interagire con l'API Google Cloud Pub/Sub.
Hai imparato a utilizzare gli adattatori del canale Spring Integration per Google Cloud Pub/Sub.
Scopri di più
- Google Cloud Pub/Sub: https://cloud.google.com/pubsub/
- Progetto Spring on GCP: http://cloud.spring.io/spring-cloud-gcp/
- Repository GitHub di Spring su GCP: https://github.com/spring-cloud/spring-cloud-gcp
- Java su Google Cloud: https://cloud.google.com/java/
Licenza
Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.