Messaggistica con l'integrazione Spring e Google Cloud Pub/Sub

1. Panoramica

L'integrazione di Spring fornisce un meccanismo di messaggistica per scambiare Messages tramite MessageChannels. Utilizza adattatori di canale per comunicare con sistemi esterni.

In questo esercizio creeremo due app che comunicano utilizzando gli adattatori di canale di Spring Integration forniti dalla piattaforma Google Cloud Spring Cloud. Questi adattatori consentono a Spring Integration di utilizzare Google Cloud Pub/Sub come backend per lo scambio dei messaggi.

Imparerai a utilizzare Cloud Shell e il comando gcloud di Cloud SDK.

Questo tutorial utilizza il codice campione della Guida introduttiva a Spring Boot.

Cosa imparerai a fare

  • Come scambiare messaggi tra app con Google Cloud Pub/Sub utilizzando l'integrazione di Spring e la piattaforma Google Cloud Spring

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?

Solo lettura Leggilo e completa gli esercizi

Come valuteresti la tua esperienza nello sviluppo di app web HTML/CSS?

Principiante Livello intermedio Eccellente

Come giudichi la tua esperienza di utilizzo dei servizi della piattaforma Google Cloud?

Principiante Livello intermedio Eccellente

2. Configurazione e requisiti

Configurazione dell'ambiente da seguire in modo autonomo

  1. Accedi alla console Google Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Il Nome progetto è il nome visualizzato dei partecipanti del progetto. Si tratta di una stringa di caratteri non utilizzata dalle API di Google. Puoi sempre aggiornarla.
  • L'ID progetto è univoco in tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo essere stato impostato). La console Cloud genera automaticamente una stringa univoca. di solito non ti importa cosa sia. Nella maggior parte dei codelab, dovrai fare riferimento al tuo ID progetto (in genere identificato come PROJECT_ID). Se l'ID generato non ti soddisfa, potresti generarne un altro casuale. In alternativa, puoi provarne una personalizzata per verificare se è disponibile. Non può essere modificato dopo questo passaggio e rimane per tutta la durata del progetto.
  • Per informazione, c'è un terzo valore, un numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
  1. Successivamente, dovrai abilitare la fatturazione nella console Cloud per utilizzare risorse/API Cloud. L'esecuzione di questo codelab non ha alcun costo. Per arrestare le risorse ed evitare di incorrere in fatturazione dopo questo tutorial, puoi eliminare le risorse che hai creato o eliminare il progetto. I nuovi utenti di Google Cloud sono idonei al programma 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 Cloud Shell

  1. Dalla console Cloud, fai clic su Attiva Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Se è la prima volta che avvii Cloud Shell, ti verrà mostrata una schermata intermedia che descrive di cosa si tratta. Se ti è stata presentata una schermata intermedia, fai clic su Continua.

9c92662c6a846a5c.png

Il provisioning e la connessione a Cloud Shell dovrebbero richiedere solo qualche istante.

9f0e51b578fecce5.png

Questa macchina virtuale viene caricata con tutti gli strumenti di sviluppo necessari. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni di rete e l'autenticazione. Gran parte, se non tutto, del lavoro in questo codelab può essere svolto con un browser.

Una volta stabilita la connessione a Cloud Shell, dovresti vedere che hai eseguito l'autenticazione e che il progetto è impostato sul tuo ID progetto.

  1. Esegui questo comando in Cloud Shell per verificare che l'account sia autenticato:
gcloud auth list

Output comando

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Esegui questo comando in Cloud Shell per confermare che il comando gcloud è a conoscenza del tuo progetto:
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].

3. Esegui il provisioning delle risorse Pub/Sub

Vai alla pagina degli argomenti Google Cloud Pub/Sub.

Fai clic su Crea argomento.

4c938409dc7169a6.png

Digita exampleTopic come nome dell'argomento e fai clic su Crea.

e2daeec91537f672.png

Dopo aver creato l'argomento, rimani nella pagina Argomenti. Cerca l'argomento appena creato, premi i tre puntini verticali alla fine della riga e fai clic su New Subscription (Nuovo abbonamento).

975efa26e5054936.png

Digita exampleSubscription nella casella di testo del nome dell'abbonamento e fai clic su Crea.

f7a91d9e1cb48009.png

4. Inizializzare le applicazioni di avvio a molla

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=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. Crea un'applicazione per inviare messaggi

Ora creiamo la nostra app per l'invio di messaggi. Passa alla directory dell'app di invio.

$ cd spring-integration-sender

Vogliamo che la nostra app scriva messaggi a un canale. Una volta che un messaggio è nel canale, viene selezionato 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 di Google Cloud Pub/Sub.

Per consentire alla nostra app di scrivere in un canale, possiamo utilizzare un gateway di messaggistica di Spring Integration. Utilizzando un editor di testo da 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 disponiamo di un meccanismo per inviare messaggi a un canale, ma dove si trovano i messaggi una volta inseriti nel canale?

È necessario un adattatore per il canale in uscita per consumare i nuovi messaggi nel canale e pubblicarli in un argomento Google Cloud Pub/Sub.

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");
  }
}

L'annotazione @ServiceActivator fa sì che questo 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 di canale in uso, ora possiamo collegare automaticamente un oggetto PubsubOutboundGateway e usarlo per scrivere un messaggio in 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 rimane in ascolto delle richieste HTTP POST, ma non senza aggiungere anche un'annotazione @RestController alla classe DemoApplication per contrassegnarlo come controller REST.

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

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

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

Assicurati che JAVA_HOME sia impostata sulla versione corretta.

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

Esegui l'app del 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 sta ascoltando richieste POST contenenti un messaggio sulla porta 8080 e sull'endpoint /postMessage, ma lo faremo più tardi.

6. Creare un'applicazione per ricevere messaggi

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.

9799bee5fea95aa6.png

Quindi, nella nuova sessione di Cloud Shell, modifica le directory nella directory dell'app ricevente:

$ cd spring-integration-receiver

Nell'app precedente, la dichiarazione del gateway di messaggistica ha creato il canale in uscita per noi. Poiché non utilizziamo un gateway di messaggistica per ricevere messaggi, dobbiamo dichiarare il nostro MessageChannel dove arriveranno i messaggi in arrivo.

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();
  }
}

Sarà necessario l'adattatore del canale in entrata per ricevere i messaggi da Google Cloud Pub/Sub e inoltrarli a pubsubInputChannel.

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;
  }
}

Questo adattatore si collega a pubsubInputChannel e ascolta i nuovi messaggi dalla sottoscrizione Google Cloud Pub/Sub exampleSubscription.

Abbiamo un canale in cui vengono pubblicati i messaggi in arrivo, ma cosa fare con questi messaggi?

Elaboriamoli con un @ServiceActivator che si attiva all'arrivo di nuovi messaggi in pubsubInputChannel. In questo caso, registreremo semplicemente il payload dei messaggi.

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);
  }
}

Assicurati che JAVA_HOME sia impostata sulla versione corretta.

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

Esegui l'app del ricevitore.

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

Ora tutti i messaggi che invii all'app del mittente verranno registrati nell'app del destinatario. Per verificarlo, apri una nuova sessione di Cloud Shell ed effettua una richiesta POST HTTP all'app del mittente.

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

Quindi, verifica che l'app del destinatario abbia registrato il messaggio che hai inviato.

INFO: Message arrived! Payload: Hello world!

7. Esegui la pulizia

Elimina la sottoscrizione e l'argomento creati nell'ambito di questo esercizio.

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

8. Riepilogo

Configuri due app Spring Boot che utilizzano gli adattatori di canale di integrazione Spring per Google Cloud Pub/Sub. Si scambiano messaggi senza mai interagire con l'API Google Cloud Pub/Sub.

9. Complimenti!

Hai imparato a utilizzare gli adattatori di canale di integrazione Spring per Google Cloud Pub/Sub.

Scopri di più

Licenza

Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.