توفّر لك Spring Integration آلية مراسلة لتبادل Messages
من خلال MessageChannels
. يستخدم محوّلات القنوات للتواصل مع الأنظمة الخارجية.
في هذا التمرين، سننشئ تطبيقَين يتواصلان باستخدام أدوات ربط قنوات Spring Integration التي يوفّرها Spring Cloud GCP. تتيح هذه المحوّلات لـ Spring Integration استخدام Google Cloud Pub/Sub كخادم خلفي لتبادل الرسائل.
ستتعرّف على كيفية استخدام Cloud Shell وأمر gcloud في Cloud SDK.
يستخدم هذا البرنامج التعليمي نموذج الرمز البرمجي من دليل بدء استخدام Spring Boot.
ما ستتعرّف عليه
- كيفية تبادل الرسائل بين التطبيقات باستخدام Google Cloud Pub/Sub من خلال Spring Integration وSpring Cloud GCP
المتطلبات
- مشروع على Google Cloud Platform
- متصفّح، مثل Chrome أو Firefox
- الإلمام بمحرّرات النصوص القياسية في Linux، مثل Vim أو EMACs أو Nano
كيف ستستخدم هذا البرنامج التعليمي؟
ما هو تقييمك لتجربة إنشاء تطبيقات ويب باستخدام HTML/CSS؟
ما هو تقييمك لتجربة استخدام خدمات Google Cloud Platform؟
إعداد البيئة بالسرعة التي تناسبك
إذا لم يكن لديك حساب على Google (Gmail أو Google Apps)، عليك إنشاء حساب. سجِّل الدخول إلى "وحدة تحكّم Google Cloud Platform" (console.cloud.google.com) وأنشِئ مشروعًا جديدًا:
تذكَّر معرّف المشروع، وهو اسم فريد في جميع مشاريع Google Cloud (الاسم أعلاه مستخدَم حاليًا ولن يكون متاحًا لك، نأسف لذلك). سيتم الإشارة إليه لاحقًا في هذا الدرس العملي باسم PROJECT_ID
.
بعد ذلك، عليك تفعيل الفوترة في Cloud Console من أجل استخدام موارد Google Cloud.
لن تكلفك تجربة هذا الدرس البرمجي أكثر من بضعة دولارات، ولكن قد تكون التكلفة أعلى إذا قررت استخدام المزيد من الموارد أو إذا تركتها قيد التشغيل (راجِع قسم "التنظيف" في نهاية هذا المستند).
يمكن للمستخدمين الجدد في Google Cloud Platform الاستفادة من فترة تجريبية مجانية بقيمة 300 دولار أمريكي.
Google Cloud Shell
على الرغم من إمكانية تشغيل Google Cloud عن بُعد من الكمبيوتر المحمول، سنستخدم في هذا الدرس العملي Google Cloud Shell، وهي بيئة سطر أوامر تعمل في السحابة الإلكترونية.
تفعيل Google Cloud Shell
من وحدة تحكّم Google Cloud Platform، انقر على رمز Cloud Shell في شريط الأدوات العلوي الأيسر:
ثم انقر على "بدء Cloud Shell":
ينبغي ألا تستغرق إدارة الحسابات والاتصال بالبيئة أكثر من بضع لحظات.
يتم تحميل هذه الآلة الافتراضية مزوّدة بكل أدوات التطوير التي ستحتاج إليها. وتوفِّر هذه الآلة دليلاً رئيسيًا دائمًا بسعة 5 غيغابايت ويتمّ تشغيله على Google Cloud، ما يحسّن كثيرًا أداء الشبكة والمصادقة. ويمكن إتمام معظم عملك إن لم يكن كلّه في هذا الدرس ببساطة من خلال متصفّح أو جهاز Google Chromebook فقط.
بعد الاتصال بـ Cloud Shell، من المفترض أن ترى أنّه تم إثبات هويتك وأنّ المشروع تم ضبطه على PROJECT_ID.
نفِّذ الأمر التالي في Cloud Shell للتأكّد من إكمال عملية المصادقة:
gcloud auth list
ناتج الأمر
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
ناتج الأمر
[core] project = <PROJECT_ID>
إذا لم يكن كذلك، يمكنك تعيينه من خلال هذا الأمر:
gcloud config set project <PROJECT_ID>
ناتج الأمر
Updated property [core/project].
انتقِل إلى صفحة مواضيع Google Cloud Pub/Sub وفعِّل واجهة برمجة التطبيقات.
انقر على إنشاء موضوع.
اكتب exampleTopic
كاسم للموضوع، ثم انقر على إنشاء.
بعد إنشاء الموضوع، ابقَ في صفحة "المواضيع". ابحث عن الموضوع الذي أنشأته للتو، وانقر على النقاط الثلاث العمودية في نهاية السطر، ثم انقر على اشتراك جديد.
اكتب exampleSubscription
في مربع النص الخاص باسم الاشتراك وانقر على إنشاء.
بعد تشغيل Cloud Shell، يمكنك استخدام سطر الأوامر لإنشاء تطبيقَين جديدَين من Spring Boot باستخدام Spring Initializr:
$ curl https://start.spring.io/starter.tgz \
-d bootVersion=2.0.6.RELEASE \
-d dependencies=web \
-d baseDir=spring-integration-sender | tar -xzvf -
$ curl https://start.spring.io/starter.tgz \
-d bootVersion=2.0.6.RELEASE \
-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 org.springframework.cloud.gcp.pubsub.core.PubSubTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.cloud.gcp.pubsub.integration.outbound.PubSubMessageHandler;
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 {
...
}
لكي يتم تشغيل التطبيق، علينا فقط إضافة التبعيات المطلوبة.
pom.xml
<project>
...
<!-- Add Spring Cloud GCP Dependency BOM -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-dependencies</artifactId>
<version>1.0.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
...
<!-- Add Pub/Sub Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
</dependency>
<!-- Add Spring Integration -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
</dependencies>
</project>
شغِّل تطبيق المُرسِل.
# 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
، ولكن سنتطرق إلى ذلك لاحقًا.
لقد أنشأنا للتو تطبيقًا يرسل الرسائل من خلال Google Cloud Pub/Sub. الآن، سننشئ تطبيقًا آخر يتلقّى هذه الرسائل ويعالجها.
انقر على + لفتح جلسة Cloud Shell جديدة.
بعد ذلك، في جلسة 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 org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.gcp.pubsub.core.PubSubTemplate;
import org.springframework.cloud.gcp.pubsub.integration.inbound.PubSubInboundChannelAdapter;
@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
ويستمع إلى الرسائل الجديدة من اشتراك exampleSubscription
في Google Cloud Pub/Sub.
لدينا قناة يتم نشر الرسائل الواردة فيها، ولكن ماذا نفعل بهذه الرسائل؟
لنبدأ بمعالجتها باستخدام @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);
}
}
في هذه الحالة، سنكتفي بتسجيل حمولة الرسالة.
علينا إضافة العناصر التابعة اللازمة.
pom.xml
<project>
...
<!-- Add Spring Cloud GCP Dependency BOM -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-dependencies</artifactId>
<version>1.0.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
...
<!-- Add Pub/Sub Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
</dependency>
<!-- Add Spring Integration -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
</dependencies>
</project>
شغِّل تطبيق جهاز الاستقبال.
$ ./mvnw spring-boot:run
الآن، سيتم تسجيل أي رسائل ترسلها إلى تطبيق المرسِل في تطبيق المستلِم. ولاختبار ذلك، افتح جلسة Cloud Shell جديدة وأرسِل طلب HTTP POST إلى تطبيق المرسِل.
$ curl --data "message=Hello world!" localhost:8080/postMessage
بعد ذلك، تأكَّد من أنّ تطبيق المستلِم سجّل الرسالة التي أرسلتها.
INFO: Message arrived! Payload: Hello world!
احذف الاشتراك والموضوع اللذين تم إنشاؤهما كجزء من هذا التمرين.
$ gcloud beta pubsub subscriptions delete exampleSubscription
$ gcloud beta pubsub topics delete exampleTopic
يمكنك إعداد تطبيقَين من Spring Boot يستخدِمان Spring Integration Channel Adapters لخدمة Google Cloud Pub/Sub. تتبادل هذه التطبيقات الرسائل فيما بينها بدون التفاعل مع واجهة برمجة التطبيقات Google Cloud Pub/Sub.
تعرّفت على كيفية استخدام "محوّلات قنوات Spring Integration" في Google Cloud Pub/Sub.
مزيد من المعلومات
- Google Cloud Pub/Sub: https://cloud.google.com/pubsub/
- مشروع Spring on GCP: http://cloud.spring.io/spring-cloud-gcp/
- مستودع Spring on GCP GitHub: https://github.com/spring-cloud/spring-cloud-gcp
- Java على Google Cloud Platform: https://cloud.google.com/java/
الترخيص
يخضع هذا العمل لترخيص Creative Commons Attribution 2.0 Generic License.