Przesyłanie wiadomości za pomocą usługi Spring Integration i Google Cloud Pub/Sub

1. Przegląd

Spring Integration udostępnia mechanizm przesyłania wiadomości do wymiany Messages za pomocą MessageChannels. Do komunikacji z systemami zewnętrznymi używa adapterów kanałów.

W tym ćwiczeniu utworzymy 2 aplikacje, które komunikują się za pomocą adapterów kanałów Spring Integration udostępnianych przez Spring Cloud GCP. Te adaptery sprawiają, że Spring Integration używa Google Cloud Pub/Sub jako backendu wymiany wiadomości.

Dowiesz się, jak używać Cloud Shell i narzędzia wiersza poleceń gcloud z pakietu Cloud SDK.

W tym samouczku używamy przykładowego kodu z przewodnika dla początkujących dotyczącego Spring Boot.

Czego się nauczysz

  • Wymiana wiadomości między aplikacjami za pomocą Google Cloud Pub/Sub przy użyciu Spring Integration i Spring Cloud GCP

Czego potrzebujesz

  • Projekt Google Cloud Platform
  • przeglądarka, np. Chrome lub Firefox;
  • Znajomość standardowych edytorów tekstu systemu Linux, takich jak Vim, EMACS lub Nano.

Jak zamierzasz korzystać z tego samouczka?

Tylko przeczytaj Przeczytaj i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenie w tworzeniu aplikacji internetowych w HTML/CSS?

Początkujący Średnio zaawansowany Zaawansowany

Jak oceniasz korzystanie z usług Google Cloud Platform?

Początkujący Średnio zaawansowany Zaawansowany

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu to wyświetlana nazwa uczestników tego projektu. Jest to ciąg znaków, który nie jest używany przez interfejsy API Google. Zawsze możesz ją zaktualizować.
  • Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić po ustawieniu. Konsola Cloud automatycznie generuje unikalny ciąg znaków. Zwykle nie musisz się nim przejmować. W większości ćwiczeń z programowania musisz odwoływać się do identyfikatora projektu (zwykle oznaczanego jako PROJECT_ID). Jeśli wygenerowany identyfikator Ci się nie podoba, możesz wygenerować inny losowy identyfikator. Możesz też spróbować własnej nazwy i sprawdzić, czy jest dostępna. Po tym kroku nie można go zmienić i pozostaje on taki przez cały czas trwania projektu.
  • Warto wiedzieć, że istnieje też trzecia wartość, numer projektu, której używają niektóre interfejsy API. Więcej informacji o tych 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w konsoli Cloud, aby korzystać z zasobów i interfejsów API Google Cloud. Wykonanie tego laboratorium nie będzie kosztować dużo, a może nawet nic. Aby wyłączyć zasoby i uniknąć naliczania opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub projekt. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego o wartości 300 USD.

Google Cloud Shell

Z Google Cloud można korzystać zdalnie na laptopie, ale w tym module użyjemy Google Cloud Shell, czyli środowiska wiersza poleceń działającego w chmurze.

Aktywowanie Cloud Shell

  1. W konsoli Cloud kliknij Aktywuj Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni z opisem tego środowiska. Jeśli pojawił się ekran pośredni, kliknij Dalej.

9c92662c6a846a5c.png

Uzyskanie dostępu do środowiska Cloud Shell i połączenie się z nim powinno zająć tylko kilka chwil.

9f0e51b578fecce5.png

Ta maszyna wirtualna zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera również stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i usprawnia proces uwierzytelniania. Większość zadań w tym module, a być może wszystkie, możesz wykonać w przeglądarce.

Po połączeniu z Cloud Shell zobaczysz, że uwierzytelnianie zostało już przeprowadzone, a projekt jest już ustawiony na Twój identyfikator projektu.

  1. Aby potwierdzić, że uwierzytelnianie zostało przeprowadzone, uruchom w Cloud Shell to polecenie:
gcloud auth list

Wynik polecenia

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project

Wynik polecenia

[core]
project = <PROJECT_ID>

Jeśli nie, możesz go ustawić za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Wynik polecenia

Updated property [core/project].

3. Provision Pub/Sub resources

Otwórz stronę tematów Google Cloud Pub/Sub.

Kliknij Utwórz temat.

4c938409dc7169a6.png

Wpisz exampleTopic jako nazwę tematu, a następnie kliknij Utwórz.

e2daeec91537f672.png

Po utworzeniu tematu pozostań na stronie Tematy. Znajdź utworzony przez siebie temat, kliknij 3 kropki na końcu wiersza i wybierz Nowa subskrypcja.

975efa26e5054936.png

Wpisz exampleSubscription w polu tekstowym nazwy subskrypcji i kliknij Utwórz.

f7a91d9e1cb48009.png

4. Inicjowanie aplikacji Spring Boot

Po uruchomieniu Cloud Shell możesz użyć wiersza poleceń, aby wygenerować 2 nowe aplikacje Spring Boot za pomocą 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. Tworzenie aplikacji do wysyłania wiadomości

Teraz utwórz aplikację do wysyłania wiadomości. Przejdź do katalogu aplikacji do wysyłania.

$ cd spring-integration-sender

Chcemy, aby nasza aplikacja mogła pisać wiadomości na kanale. Gdy wiadomość znajdzie się w kanale, zostanie pobrana przez adapter kanału wychodzącego, który przekształci ją z ogólnej wiadomości Spring w wiadomość Google Cloud Pub/Sub i opublikuje ją w temacie Google Cloud Pub/Sub.

Aby nasza aplikacja mogła zapisywać dane w kanale, możemy użyć bramy przesyłania wiadomości Spring Integration. W edytorze tekstu z vim, emacs lub nano zadeklaruj interfejs PubsubOutboundGateway w klasie 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);
  }
}

Mamy już mechanizm wysyłania wiadomości na kanał, ale co się z nimi dzieje, gdy już tam trafią?

Potrzebujemy adaptera kanału wychodzącego, aby odbierać nowe wiadomości na kanale i publikować je w temacie 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");
  }
}

Adnotacja @ServiceActivator powoduje, że ten MessageHandler jest stosowany do wszystkich nowych wiadomości w grupie inputChannel. W tym przypadku wywołujemy nasz adapter kanału wychodzącego PubSubMessageHandler, aby opublikować wiadomość w temacie exampleTopic usługi Google Cloud Pub/Sub.

Po umieszczeniu adaptera kanału możemy teraz automatycznie połączyć obiekt PubsubOutboundGateway i użyć go do zapisania wiadomości w kanale.

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

Dzięki adnotacji @PostMapping mamy teraz punkt końcowy, który nasłuchuje żądań HTTP POST, ale nie bez dodania adnotacji @RestController do klasy DemoApplication, aby oznaczyć ją jako kontroler REST.

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

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

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

Sprawdź, czy JAVA_HOME jest ustawiony na odpowiednią wersję.

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

Uruchom aplikację nadawcy.

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

$ ./mvnw spring-boot:run

Aplikacja nasłuchuje żądań POST zawierających wiadomość na porcie 8080 i w punkcie końcowym /postMessage, ale do tego wrócimy później.

6. Tworzenie aplikacji do odbierania wiadomości

Właśnie utworzyliśmy aplikację, która wysyła wiadomości za pomocą Google Cloud Pub/Sub. Teraz utworzymy kolejną aplikację, która będzie odbierać te wiadomości i je przetwarzać.

Kliknij +, aby otworzyć nową sesję Cloud Shell.

9799bee5fea95aa6.png

Następnie w nowej sesji Cloud Shell przejdź do katalogu aplikacji odbiorcy:

$ cd spring-integration-receiver

W poprzedniej aplikacji deklaracja bramy wiadomości tworzyła dla nas kanał wychodzący. Ponieważ nie używamy bramy do odbierania wiadomości, musimy zadeklarować własny adres MessageChannel, na który będą przychodzić wiadomości.

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

Będziemy potrzebować adaptera kanału przychodzącego, aby odbierać wiadomości z Google Cloud Pub/Sub i przekazywać je do 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;
  }
}

Ten adapter wiąże się z pubsubInputChannel i nasłuchuje nowych wiadomości z subskrypcji exampleSubscription Google Cloud Pub/Sub.

Mamy kanał, na którym publikowane są wiadomości przychodzące, ale co z nimi zrobić?

Przetwórzmy je za pomocą @ServiceActivator, które jest wywoływane, gdy nowe wiadomości docierają do pubsubInputChannel. W takim przypadku zarejestrujemy tylko ładunek wiadomości.

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

Sprawdź, czy JAVA_HOME jest ustawiony na odpowiednią wersję.

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

Uruchom aplikację odbiornika.

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

Teraz wszystkie wiadomości wysyłane do aplikacji nadawcy będą logowane w aplikacji odbiorcy. Aby to sprawdzić, otwórz nową sesję Cloud Shell i wyślij żądanie HTTP POST do aplikacji nadawcy.

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

Następnie sprawdź, czy aplikacja odbiorcy zarejestrowała wysłaną przez Ciebie wiadomość.

INFO: Message arrived! Payload: Hello world!

7. Czyszczenie

Usuń subskrypcję i temat utworzone w ramach tego ćwiczenia.

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

8. Podsumowanie

Skonfigurujesz 2 aplikacje Spring Boot, które korzystają z adapterów kanałów Spring Integration dla Google Cloud Pub/Sub. Wymieniają one między sobą wiadomości bez wchodzenia w interakcję z interfejsem Google Cloud Pub/Sub API.

9. Gratulacje!

Wiesz już, jak używać adapterów kanałów Spring Integration dla Google Cloud Pub/Sub.

Więcej informacji

Licencja

To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.