Nhắn tin với tích hợp Spring và Google Cloud Pub/Sub

1. Tổng quan

Tích hợp Spring cung cấp cho bạn cơ chế nhắn tin để trao đổi Messages thông qua MessageChannels. Giao thức này sử dụng bộ chuyển đổi kênh để giao tiếp với các hệ thống bên ngoài.

Trong bài tập này, chúng ta sẽ tạo 2 ứng dụng giao tiếp bằng bộ chuyển đổi kênh tích hợp Spring do Spring Cloud GCP cung cấp. Các bộ chuyển đổi này giúp tiện ích tích hợp Spring sử dụng Google Cloud Pub/Sub làm phần phụ trợ trao đổi tin nhắn.

Bạn sẽ tìm hiểu cách sử dụng Cloud Shell và lệnh gcloud của Cloud SDK.

Hướng dẫn này sử dụng mã mẫu trong hướng dẫn Bắt đầu khởi động mùa xuân.

Kiến thức bạn sẽ học được

  • Cách trao đổi tin nhắn giữa các ứng dụng với Google Cloud Pub/Sub bằng cách sử dụng Spring Integration và Spring Cloud GCP

Bạn cần có

  • Một dự án trên Google Cloud Platform
  • Một trình duyệt, chẳng hạn như Chrome hoặc Firefox
  • Quen thuộc với các trình soạn thảo văn bản tiêu chuẩn của Linux như Vim, EMAC hoặc Nano

Bạn sẽ dùng hướng dẫn này như thế nào?

Chỉ có thể đọc Đọc và hoàn thành bài tập

Bạn đánh giá thế nào về kinh nghiệm xây dựng ứng dụng web HTML/CSS?

Người mới tập Trung cấp Thành thạo

Bạn đánh giá trải nghiệm sử dụng các dịch vụ của Google Cloud Platform như thế nào?

Người mới tập Trung cấp Thành thạo

2. Thiết lập và yêu cầu

Thiết lập môi trường theo tiến độ riêng

  1. Đăng nhập vào Google Cloud Console rồi tạo dự án mới hoặc sử dụng lại dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Tên dự án là tên hiển thị của những người tham gia dự án này. Đây là một chuỗi ký tự không được API của Google sử dụng. Bạn luôn có thể cập nhật ứng dụng.
  • Mã dự án là duy nhất trong tất cả các dự án Google Cloud và không thể thay đổi (không thể thay đổi sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường bạn không quan tâm đến sản phẩm đó là gì. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham khảo Mã dự án (thường được xác định là PROJECT_ID). Nếu không thích mã đã tạo, bạn có thể tạo một mã nhận dạng ngẫu nhiên khác. Ngoài ra, bạn có thể thử cách riêng của mình để xem có thể sử dụng hay không. Bạn không thể thay đổi mã này sau bước này và mã vẫn giữ nguyên trong thời gian của dự án.
  • Đối với thông tin của bạn, có giá trị thứ ba, Project Number (Số dự án), mà một số API sử dụng. Tìm hiểu thêm về cả ba giá trị này trong tài liệu này.
  1. Tiếp theo, bạn sẽ phải bật tính năng thanh toán trong Cloud Console để sử dụng API/tài nguyên trên đám mây. Việc chạy qua lớp học lập trình này sẽ không tốn nhiều chi phí. Để tắt các tài nguyên nhằm tránh phát sinh việc thanh toán ngoài hướng dẫn này, bạn có thể xoá các tài nguyên bạn đã tạo hoặc xoá dự án. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí 300 USD.

Google Cloud Shell

Mặc dù bạn có thể vận hành Google Cloud từ xa trên máy tính xách tay, nhưng trong lớp học lập trình này, chúng ta sẽ sử dụng Google Cloud Shell, một môi trường dòng lệnh chạy trong Đám mây.

Kích hoạt Cloud Shell

  1. Trong Cloud Console, hãy nhấp vào Kích hoạt Cloud Shell 853e55310c205094.pngs.

55efc1aaa7a4d3ad.pngS

Nếu đây là lần đầu tiên khởi động Cloud Shell, bạn sẽ thấy một màn hình trung gian mô tả về Cloud Shell. Nếu bạn nhìn thấy màn hình trung gian, hãy nhấp vào Tiếp tục.

9c92662c6a846a5c.pngS

Quá trình cấp phép và kết nối với Cloud Shell chỉ mất vài phút.

9f0e51b578fecce5.pngs

Máy ảo này được tải tất cả các công cụ phát triển cần thiết. Dịch vụ này cung cấp thư mục gốc có dung lượng ổn định 5 GB và chạy trên Google Cloud, giúp nâng cao đáng kể hiệu suất và khả năng xác thực của mạng. Nhiều (nếu không nói là) tất cả công việc của bạn trong lớp học lập trình này đều có thể thực hiện bằng trình duyệt.

Sau khi kết nối với Cloud Shell, bạn sẽ thấy mình đã được xác thực và dự án được đặt thành mã dự án.

  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng bạn đã được xác thực:
gcloud auth list

Kết quả lệnh

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn:
gcloud config list project

Kết quả lệnh

[core]
project = <PROJECT_ID>

Nếu chưa, bạn có thể thiết lập chế độ này bằng lệnh sau:

gcloud config set project <PROJECT_ID>

Kết quả lệnh

Updated property [core/project].

3. Cung cấp tài nguyên Pub/Sub

Chuyển đến trang chủ đề của Google Cloud Pub/Sub.

Nhấp vào Tạo chủ đề.

4c938409dc7169a6.png.

Nhập exampleTopic làm tên chủ đề rồi nhấp vào Tạo.

e2daeec91537f672.png

Sau khi tạo chủ đề, bạn vẫn ở lại trang Chủ đề. Tìm chủ đề mà bạn vừa tạo, nhấn vào biểu tượng ba dấu chấm dọc ở cuối dòng rồi nhấp vào Gói thuê bao mới.

975efa26e5054936.pngS

Nhập exampleSubscription vào hộp văn bản tên gói thuê bao rồi nhấp vào Tạo.

f7a91d9e1cb48009.png

4. Khởi chạy ứng dụng khởi động mùa xuân

Sau khi Cloud Shell chạy, bạn có thể sử dụng dòng lệnh để tạo 2 ứng dụng mới có tên Spring Boot bằng Spring Boot:

$ 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. Tạo ứng dụng để gửi thư

Bây giờ, hãy tạo ứng dụng gửi tin nhắn. Thay đổi sang thư mục của ứng dụng gửi.

$ cd spring-integration-sender

Chúng ta muốn ứng dụng của mình viết tin nhắn cho một kênh. Sau khi tin nhắn ở trên kênh, tin nhắn sẽ được bộ chuyển đổi kênh tiếp nhận tiếp nhận. Bộ chuyển đổi này sẽ chuyển đổi tin nhắn từ một thông báo Spring chung thành thông báo Google Cloud Pub/Sub và xuất bản tin nhắn đó lên một chủ đề của Google Cloud Pub/Sub.

Để ứng dụng của chúng ta ghi vào một kênh, chúng ta có thể sử dụng cổng thông báo tích hợp mùa xuân. Sử dụng trình chỉnh sửa văn bản của vim, emacs hoặc nano, khai báo giao diện PubsubOutboundGateway bên trong lớp 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);
  }
}

Chúng tôi hiện có cơ chế gửi thông báo đến một kênh, nhưng những thông báo đó sẽ được gửi đi đâu sau khi chúng đã ở trên kênh?

Chúng tôi cần một bộ chuyển đổi kênh đi để xem tin nhắn mới trong kênh và xuất bản chúng lên một chủ đề trên 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");
  }
}

Chú giải @ServiceActivator khiến MessageHandler này được áp dụng cho mọi tin nhắn mới trong inputChannel. Trong trường hợp này, chúng ta đang gọi bộ chuyển đổi kênh đi là PubSubMessageHandler để xuất bản thông báo lên chủ đề exampleTopic của Google Cloud Pub/Sub.

Với bộ chuyển đổi kênh đã sẵn sàng, giờ đây chúng ta có thể tự động kết nối dây đối tượng PubsubOutboundGateway và sử dụng đối tượng này để viết thông báo tới kênh.

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

Do chú thích @PostMapping, chúng ta hiện có một điểm cuối đang nghe các yêu cầu POST qua HTTP, nhưng vẫn có thể thêm chú thích @RestController vào lớp DemoApplication để đánh dấu là trình điều khiển REST.

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

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

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

Hãy nhớ đặt JAVA_HOME về đúng phiên bản.

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

Chạy ứng dụng gửi.

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

$ ./mvnw spring-boot:run

Ứng dụng đang nghe các yêu cầu POST chứa thông báo trên cổng 8080 và điểm cuối /postMessage, nhưng chúng ta sẽ tìm hiểu về vấn đề này sau.

6. Tạo ứng dụng để nhận thông báo

Chúng tôi vừa tạo một ứng dụng có chức năng gửi tin nhắn qua Google Cloud Pub/Sub. Bây giờ, chúng ta sẽ tạo một ứng dụng khác nhận và xử lý các tin nhắn đó.

Nhấp vào dấu + để mở một phiên Cloud Shell mới.

9799bee5fea95aa6.pngS

Sau đó, trong phiên Cloud Shell mới, hãy thay đổi các thư mục thành thư mục của ứng dụng nhận:

$ cd spring-integration-receiver

Trong ứng dụng trước, phần khai báo cổng thư đến đã tạo kênh đi cho chúng ta. Vì chúng ta không sử dụng cổng nhắn tin để nhận thư, nên chúng ta cần khai báo MessageChannel của riêng mình để nhận thư đến.

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

Chúng tôi cần có bộ chuyển đổi kênh đến để nhận tin nhắn từ Google Cloud Pub/Sub và chuyển tiếp tin nhắn đó tới 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;
  }
}

Bộ chuyển đổi này tự liên kết với pubsubInputChannel và nghe các tin nhắn mới từ gói thuê bao Google Cloud Pub/Sub exampleSubscription.

Chúng ta có kênh nơi các tin nhắn đến được đăng lên, nhưng những tin nhắn đó được làm gì?

Hãy xử lý chúng bằng @ServiceActivator được kích hoạt khi có thư mới đến pubsubInputChannel. Trong trường hợp này, chúng ta sẽ chỉ ghi nhật ký phần tải trọng của thư.

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

Hãy nhớ đặt JAVA_HOME về đúng phiên bản.

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

Chạy ứng dụng nhận.

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

Giờ đây, mọi tin nhắn bạn gửi đến ứng dụng của người gửi sẽ được ghi lại trên ứng dụng nhận. Để kiểm tra điều đó, hãy mở một phiên Cloud Shell mới và gửi yêu cầu POST qua HTTP tới ứng dụng của người gửi.

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

Sau đó, hãy xác minh rằng ứng dụng nhận tin nhắn mà bạn gửi đã ghi lại!

INFO: Message arrived! Payload: Hello world!

7. Dọn dẹp

Xoá gói thuê bao và chủ đề đã tạo trong bài tập này.

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

8. Tóm tắt

Bạn thiết lập 2 ứng dụng Spring Boot dùng Bộ chuyển đổi kênh tích hợp Spring dành cho Google Cloud Pub/Sub. Họ trao đổi tin nhắn với nhau mà không tương tác với API Google Cloud Pub/Sub.

9. Xin chúc mừng!

Bạn đã tìm hiểu cách sử dụng Bộ chuyển đổi kênh tích hợp Spring dành cho Google Cloud Pub/Sub!

Tìm hiểu thêm

Giấy phép

Tác phẩm này được cấp phép theo Giấy phép chung Ghi nhận tác giả Creative Commons 2.0.