پیام رسانی با Spring Integration و Google Cloud Pub/Sub

۱. مرور کلی

Spring Integration یک مکانیزم پیام‌رسانی برای تبادل Messages از طریق MessageChannels در اختیار شما قرار می‌دهد. این مکانیزم از آداپتورهای کانال برای ارتباط با سیستم‌های خارجی استفاده می‌کند.

در این تمرین، دو برنامه ایجاد خواهیم کرد که با استفاده از آداپتورهای کانال Spring Integration که توسط Spring Cloud GCP ارائه می‌شوند، ارتباط برقرار می‌کنند. این آداپتورها باعث می‌شوند Spring Integration از Google Cloud Pub/Sub به عنوان backend تبادل پیام استفاده کند.

شما یاد خواهید گرفت که چگونه از Cloud Shell و دستور gcloud مربوط به Cloud SDK استفاده کنید.

این آموزش از کد نمونه موجود در راهنمای شروع به کار با Spring Boot استفاده می‌کند.

آنچه یاد خواهید گرفت

  • نحوه تبادل پیام بین برنامه‌ها با Google Cloud Pub/Sub با استفاده از Spring Integration و Spring Cloud GCP

آنچه نیاز دارید

  • یک پروژه پلتفرم ابری گوگل
  • یک مرورگر، مانند کروم یا فایرفاکس
  • آشنایی با ویرایشگرهای متن استاندارد لینوکس مانند Vim، EMACs یا Nano

چگونه از این آموزش استفاده خواهید کرد؟

فقط تا انتها بخوانید آن را بخوانید و تمرین‌ها را انجام دهید

تجربه خود را در ساخت برنامه‌های وب HTML/CSS چگونه ارزیابی می‌کنید؟

تازه کار متوسط ماهر

تجربه خود را در استفاده از خدمات پلتفرم ابری گوگل چگونه ارزیابی می‌کنید؟

تازه کار متوسط ماهر

۲. تنظیمات و الزامات

تنظیم محیط خودتنظیم

  1. وارد کنسول گوگل کلود شوید و یک پروژه جدید ایجاد کنید یا از یک پروژه موجود دوباره استفاده کنید. اگر از قبل حساب جیمیل یا گوگل ورک اسپیس ندارید، باید یکی ایجاد کنید .

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • نام پروژه، نام نمایشی برای شرکت‌کنندگان این پروژه است. این یک رشته کاراکتری است که توسط APIهای گوگل استفاده نمی‌شود. شما همیشه می‌توانید آن را به‌روزرسانی کنید.
  • شناسه پروژه در تمام پروژه‌های گوگل کلود منحصر به فرد است و تغییرناپذیر است (پس از تنظیم، قابل تغییر نیست). کنسول کلود به طور خودکار یک رشته منحصر به فرد تولید می‌کند؛ معمولاً برای شما مهم نیست که چه باشد. در اکثر آزمایشگاه‌های کد، باید شناسه پروژه خود را (که معمولاً با عنوان PROJECT_ID شناخته می‌شود) ارجاع دهید. اگر شناسه تولید شده را دوست ندارید، می‌توانید یک شناسه تصادفی دیگر ایجاد کنید. به عنوان یک جایگزین، می‌توانید شناسه خودتان را امتحان کنید و ببینید که آیا در دسترس است یا خیر. پس از این مرحله قابل تغییر نیست و در طول پروژه باقی می‌ماند.
  • برای اطلاع شما، یک مقدار سوم، شماره پروژه ، وجود دارد که برخی از APIها از آن استفاده می‌کنند. برای کسب اطلاعات بیشتر در مورد هر سه این مقادیر، به مستندات مراجعه کنید.
  1. در مرحله بعد، برای استفاده از منابع/API های ابری، باید پرداخت صورتحساب را در کنسول ابری فعال کنید . اجرای این آزمایشگاه کد هزینه زیادی نخواهد داشت، اگر اصلاً هزینه‌ای داشته باشد. برای خاموش کردن منابع به منظور جلوگیری از پرداخت صورتحساب پس از این آموزش، می‌توانید منابعی را که ایجاد کرده‌اید یا پروژه را حذف کنید. کاربران جدید Google Cloud واجد شرایط برنامه آزمایشی رایگان ۳۰۰ دلاری هستند.

پوسته ابری گوگل

اگرچه می‌توان از راه دور و از طریق لپ‌تاپ، گوگل کلود را مدیریت کرد، اما در این آزمایشگاه کد، ما از گوگل کلود شل ، یک محیط خط فرمان که در فضای ابری اجرا می‌شود، استفاده خواهیم کرد.

فعال کردن پوسته ابری

  1. از کنسول ابری، روی فعال کردن پوسته ابری کلیک کنید 853e55310c205094.png .

55efc1aaa7a4d3ad.png

اگر این اولین باری است که Cloud Shell را اجرا می‌کنید، یک صفحه میانی برای توضیح آن به شما نمایش داده می‌شود. اگر با یک صفحه میانی مواجه شدید، روی ادامه کلیک کنید.

9c92662c6a846a5c.png

آماده‌سازی و اتصال به Cloud Shell فقط چند لحظه طول می‌کشد.

9f0e51b578fecce5.png

این ماشین مجازی مجهز به تمام ابزارهای توسعه مورد نیاز است. این ماشین یک دایرکتوری خانگی پایدار ۵ گیگابایتی ارائه می‌دهد و در فضای ابری گوگل اجرا می‌شود که عملکرد شبکه و احراز هویت را تا حد زیادی افزایش می‌دهد. بخش عمده‌ای از کار شما در این آزمایشگاه کد، اگر نگوییم همه، را می‌توان با یک مرورگر انجام داد.

پس از اتصال به Cloud Shell، باید ببینید که احراز هویت شده‌اید و پروژه روی شناسه پروژه شما تنظیم شده است.

  1. برای تأیید احراز هویت، دستور زیر را در Cloud Shell اجرا کنید:
gcloud auth list

خروجی دستور

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. دستور زیر را در Cloud Shell اجرا کنید تا تأیید کنید که دستور gcloud از پروژه شما اطلاع دارد:
gcloud config list project

خروجی دستور

[core]
project = <PROJECT_ID>

اگر اینطور نیست، می‌توانید با این دستور آن را تنظیم کنید:

gcloud config set project <PROJECT_ID>

خروجی دستور

Updated property [core/project].

۳. منابع میخانه/فرعی تأمین

به صفحه «مطالب عمومی/زیرموضوعات» گوگل کلود بروید.

روی ایجاد موضوع کلیک کنید.

4c938409dc7169a6.png

عبارت exampleTopic را به عنوان نام موضوع تایپ کنید و سپس روی ایجاد کلیک کنید.

e2daeec91537f672.png

پس از ایجاد موضوع، در صفحه موضوعات بمانید. موضوعی را که تازه ایجاد کرده‌اید پیدا کنید، سه نقطه عمودی را در انتهای خط فشار دهید و روی «اشتراک جدید» کلیک کنید.

975efa26e5054936.png

عبارت exampleSubscription را در کادر متن نام اشتراک تایپ کنید و روی ایجاد کلیک کنید.

f7a91d9e1cb48009.png

۴. مقداردهی اولیه برنامه‌های Spring Boot

پس از راه‌اندازی Cloud Shell، می‌توانید از خط فرمان برای تولید دو برنامه Spring Boot جدید با 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 -

۵. یک برنامه برای ارسال پیام ایجاد کنید

حالا بیایید برنامه ارسال پیام خود را ایجاد کنیم. به دایرکتوری برنامه ارسال بروید.

$ cd spring-integration-sender

ما می‌خواهیم برنامه ما پیام‌هایی را در یک کانال بنویسد. پس از اینکه پیامی در کانال قرار گرفت، توسط آداپتور کانال خروجی دریافت می‌شود که آن را از یک پیام عمومی Spring به یک پیام Google Cloud Pub/Sub تبدیل کرده و در یک موضوع Google Cloud Pub/Sub منتشر می‌کند.

برای اینکه برنامه ما بتواند در یک کانال بنویسد، می‌توانیم از یک دروازه پیام‌رسانی Spring Integration استفاده کنیم. با استفاده از یک ویرایشگر متن از vim ، emacs یا nano ، یک رابط PubsubOutboundGateway را درون کلاس 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);
  }
}

اکنون ما مکانیزمی برای ارسال پیام به یک کانال داریم، اما این پیام‌ها پس از قرار گرفتن در کانال کجا می‌روند؟

ما به یک آداپتور کانال خروجی نیاز داریم تا پیام‌های جدید را در کانال دریافت کرده و آنها را در یک موضوع 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");
  }
}

حاشیه‌نویسی @ServiceActivator باعث می‌شود که این MessageHandler به هر پیام جدیدی در inputChannel اعمال شود. در این حالت، ما آداپتور کانال خروجی خود، PubSubMessageHandler ، را فراخوانی می‌کنیم تا پیام را در موضوع exampleTopic مربوط به Google Cloud Pub/Sub منتشر کند.

با قرار دادن آداپتور کانال، اکنون می‌توانیم یک شیء PubsubOutboundGateway را به صورت خودکار سیم‌کشی کنیم و از آن برای نوشتن پیام در یک کانال استفاده کنیم.

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

به دلیل حاشیه‌نویسی @PostMapping ، اکنون یک نقطه پایانی داریم که به درخواست‌های HTTP POST گوش می‌دهد، اما بدون اضافه کردن یک حاشیه‌نویسی @RestController به کلاس DemoApplication برای علامت‌گذاری آن به عنوان یک کنترلر REST، این کار را انجام می‌دهیم.

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

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

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

مطمئن شوید که JAVA_HOME روی نسخه صحیح تنظیم شده است.

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

برنامه فرستنده را اجرا کنید.

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

$ ./mvnw spring-boot:run

برنامه در حال گوش دادن به درخواست‌های POST حاوی پیامی روی پورت ۸۰۸۰ و نقطه پایانی /postMessage است، اما بعداً به این موضوع خواهیم پرداخت.

۶. یک برنامه برای دریافت پیام‌ها ایجاد کنید

ما همین الان یک برنامه ساختیم که از طریق Google Cloud Pub/Sub پیام ارسال می‌کند. حالا، یک برنامه دیگر می‌سازیم که آن پیام‌ها را دریافت و پردازش می‌کند.

برای باز کردن یک جلسه جدید Cloud Shell، روی + کلیک کنید.

9799bee5fea95aa6.png

سپس، در جلسه جدید Cloud Shell، دایرکتوری‌ها را به دایرکتوری برنامه گیرنده تغییر دهید:

$ cd spring-integration-receiver

در برنامه قبلی، اعلان دروازه پیام‌رسانی، کانال خروجی را برای ما ایجاد کرد. از آنجایی که ما از دروازه پیام‌رسانی برای دریافت پیام‌ها استفاده نمی‌کنیم، باید MessageChannel خودمان را که پیام‌های ورودی به آن می‌رسند، اعلان کنیم.

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

ما به آداپتور کانال ورودی نیاز داریم تا پیام‌ها را از Google Cloud Pub/Sub دریافت کرده و آنها را به 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;
  }
}

این آداپتور خود را به pubsubInputChannel متصل می‌کند و به پیام‌های جدید از اشتراک Google Cloud Pub/Sub exampleSubscription گوش می‌دهد.

ما یک کانال داریم که پیام‌های دریافتی در آن ارسال می‌شوند، اما با آن پیام‌ها چه باید کرد؟

بیایید آنها را با یک @ServiceActivator پردازش کنیم که هنگام رسیدن پیام‌های جدید به 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);
  }
}

مطمئن شوید که JAVA_HOME روی نسخه صحیح تنظیم شده است.

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

برنامه گیرنده را اجرا کنید.

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

اکنون هر پیامی که به برنامه فرستنده ارسال می‌کنید، در برنامه گیرنده ثبت می‌شود. برای آزمایش این موضوع، یک جلسه جدید Cloud Shell باز کنید و یک درخواست HTTP POST به برنامه فرستنده ارسال کنید.

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

سپس، تأیید کنید که برنامه گیرنده، پیامی را که ارسال کرده‌اید، ثبت کرده است!

INFO: Message arrived! Payload: Hello world!

۷. پاکسازی

اشتراک و موضوعی که به عنوان بخشی از این تمرین ایجاد شده است را حذف کنید.

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

۸. خلاصه

شما دو برنامه Spring Boot راه‌اندازی می‌کنید که از آداپتورهای کانال یکپارچه‌سازی Spring برای Google Cloud Pub/Sub استفاده می‌کنند. آن‌ها بدون هیچ تعاملی با Google Cloud Pub/Sub API، پیام‌ها را بین خود رد و بدل می‌کنند.

۹. تبریک می‌گویم!

شما یاد گرفتید که چگونه از آداپتورهای کانال یکپارچه‌سازی اسپرینگ برای Google Cloud Pub/Sub استفاده کنید!

اطلاعات بیشتر

مجوز

این اثر تحت مجوز عمومی Creative Commons Attribution 2.0 منتشر شده است.