المراسلة من خلال Spring Integration وGoogle Cloud Pub/Sub

1. نظرة عامة

يوفّر لك Spring Integration آلية للمراسلة لتبادل Messages من خلال MessageChannels. فهو يستخدم محوّلات القناة للاتصال بالأنظمة الخارجية.

في هذا التمرين، سننشئ تطبيقين يتصلان باستخدام محوّلات قنوات Spring Integration المقدَّمة من Spring Cloud GCP. وتجعل هذه المحوّلات Spring Integration تستخدم Google Cloud Pub/Sub كخلفية لتبادل الرسائل.

وستتعلّم كيفية استخدام Cloud Shell وأمر gcloud SDK للسحابة الإلكترونية.

يستخدم هذا البرنامج التعليمي نموذج الرمز الوارد في دليل بدء تشغيل Spring Boot.

المعلومات التي ستطّلع عليها

  • طريقة تبادل الرسائل بين التطبيقات من خلال Google Cloud Pub/Sub باستخدام Spring Integration وSpring Cloud GCP

المتطلبات

  • مشروع Google Cloud Platform
  • متصفح، مثل Chrome أو Firefox
  • الإلمام بأدوات تحرير النصوص القياسية في Linux مثل Vim أو EMAC أو Nano

كيف ستستخدم هذا البرنامج التعليمي؟

القراءة فقط اقرأها وأكمِل التمارين

كيف تقيّم تجربتك في إنشاء تطبيقات ويب بتنسيق HTML/CSS؟

حديث متوسط بارع

ما هو تقييمك لتجربتك في استخدام خدمات Google Cloud Platform؟

حديث متوسط بارع

2. الإعداد والمتطلبات

إعداد بيئة ذاتية

  1. سجِّل الدخول إلى Google Cloud Console وأنشئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • اسم المشروع هو الاسم المعروض للمشاركين في هذا المشروع. وهي سلسلة أحرف لا تستخدمها Google APIs. ويمكنك تعديلها في أي وقت.
  • يكون رقم تعريف المشروع فريدًا في جميع مشاريع Google Cloud وغير قابل للتغيير (لا يمكن تغييره بعد تحديده). تنشئ Cloud Console سلسلة فريدة تلقائيًا. فعادةً لا تهتم بما هو. في معظم الدروس التطبيقية حول الترميز، يجب الإشارة إلى رقم تعريف المشروع (الذي يتم تحديده عادةً على أنّه PROJECT_ID). وإذا لم يعجبك رقم التعريف الذي تم إنشاؤه، يمكنك إنشاء رقم تعريف عشوائي آخر. ويمكنك بدلاً من ذلك تجربة طلبك الخاص ومعرفة ما إذا كان متاحًا. ولا يمكن تغييره بعد هذه الخطوة ويبقى طوال مدة المشروع.
  • لمعلوماتك، هناك قيمة ثالثة، وهي رقم المشروع، الذي تستخدمه بعض واجهات برمجة التطبيقات. اطّلِع على مزيد من المعلومات حول هذه القيم الثلاث في المستندات.
  1. بعد ذلك، عليك تفعيل الفوترة في Cloud Console لاستخدام الموارد/واجهات برمجة التطبيقات في Cloud. لن يؤدي إكمال هذا الدرس التطبيقي حول الترميز إلى فرض أي تكاليف، إن وُجدت. لإيقاف تشغيل الموارد لتجنب تحمُّل الفواتير إلى ما هو أبعد من هذا البرنامج التعليمي، يمكنك حذف الموارد التي أنشأتها أو حذف المشروع. يكون مستخدمو Google Cloud الجدد مؤهَّلون للانضمام إلى برنامج فترة تجريبية مجانية بقيمة 300 دولار أمريكي.

Google Cloud Shell

يمكن إدارة Google Cloud عن بُعد من الكمبيوتر المحمول، ولكن في هذا الدرس التطبيقي حول الترميز، سنستخدم Google Cloud Shell، وهي بيئة سطر أوامر يتم تشغيلها في السحابة الإلكترونية.

تفعيل Cloud Shell

  1. من Cloud Console، انقر على تفعيل Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

إذا كانت هذه هي المرة الأولى التي تبدأ فيها Cloud Shell، ستظهر لك شاشة وسيطة تصف ماهيتها. إذا ظهرت لك شاشة وسيطة، انقر على متابعة.

9c92662c6a846a5c.png

من المفترَض أن تستغرق عملية توفير المتطلبات اللازمة والاتصال بخدمة Cloud Shell بضع دقائق فقط.

9f0e51b578fecce5.png

يتم تحميل هذا الجهاز الافتراضي مع جميع أدوات التطوير اللازمة. وتوفّر هذه الشبكة دليلاً رئيسيًا دائمًا بسعة 5 غيغابايت ويتم تشغيله في Google Cloud، ما يحسّن بشكل كبير من أداء الشبكة والمصادقة. يمكنك تنفيذ معظم عملك، إن لم يكن كلّه، في هذا الدرس التطبيقي حول الترميز باستخدام متصفّح.

بعد الربط بخدمة 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].

3- توفير موارد النشر/الاشتراك

انتقِل إلى صفحة مواضيع Google Cloud Pub/Sub.

انقر على إنشاء موضوع.

4c938409dc7169a6.png

اكتب exampleTopic كاسم للموضوع، ثم انقر على إنشاء.

e2daeec91537f672.png

بعد إنشاء الموضوع، ابقَ في صفحة "المواضيع". ابحث عن الموضوع الذي أنشأته للتو، واضغط على النقاط العمودية الثلاث في نهاية السطر وانقر على اشتراك جديد.

975efa26e5054936.png

اكتب exampleSubscription في مربّع نص اسم الاشتراك وانقر على إنشاء.

f7a91d9e1cb48009.png

4. إعداد تطبيقات التمهيد الربيعي

بعد إطلاق Cloud Shell، يمكنك استخدام سطر الأوامر لإنشاء تطبيقين جديدين لـ Spring Boots باستخدام 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- إنشاء تطبيق لإرسال الرسائل

لننشئ الآن تطبيق إرسال الرسائل. يمكنك التغيير إلى دليل التطبيق المُرسِل.

$ 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 التي تتضمن رسالة على المنفذ 8080 ونقطة النهاية /postMessage، لكننا سنتطرق إليه لاحقًا.

6- إنشاء تطبيق لتلقّي الرسائل

لقد أنشأنا للتو تطبيقًا لإرسال الرسائل من خلال 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!

7. تنظيف

احذف الاشتراك والموضوع اللذين تم إنشاؤهما كجزء من هذا التمرين.

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

8. ملخّص

يمكنك إعداد تطبيقَين في Spring Boot يستخدمان محوّلات قنوات Spring Integration في Google Cloud Pub/Sub. حيث يتبادلون الرسائل فيما بينهم بدون التفاعل على الإطلاق مع واجهة برمجة تطبيقات Google Cloud Pub/Sub.

9. تهانينا!

لقد تعلّمت كيفية استخدام Spring Integration Channel Adapters في Google Cloud Pub/Sub.

مزيد من المعلومات

الترخيص

هذا العمل مرخّص بموجب رخصة المشاع الإبداعي 2.0 مع نسب العمل إلى مؤلف عام.