به قسمت چهارم از سری مقاله های آموزش NATS خوش آمدید. تا این مرحله ما با NATS و کاربردهای آن در معماری میکروسرویس آشنا شدیم و دانستیم که بخاطر سرعت بالا و سهولت در استفاده، می تواند در سناریوهای متعددی جایگزینی خوب برای RabbitMQ و Kafka باشد. سپس به سراغ یکی از اصلی ترین کاربردهای NATS و سیستم های Message Oriented Middleware ها یعنی Publisher/Subscriber (منتشر کننده - مصرف کننده پیام) رفتیم و گفتیم که چطور NATS این حالت از انتشار و استفاده از پیام را پشتیبانی می کند. در قسمت سوم از این سری مقاله ها هم آموزش پیاده سازی روش Request/Reply در NATS را داشتیم که در انتهای آن یک تکه کد هم با زبان گولنگ ارائه دادم تا بتوانید با استفاده از آن این ویژگی را در محصول خود پیاده کنید.
پیشنهاد میکنم در صورتی که از این مقاله شروع به خواندن کرده اید و آشنایی با NATS ندارید، ابتدا قسمت های قبلی را بخوانید و بعد به این بخش برگردید.
در بخش چهارم یکی از کاربردهای جذاب NATS را بررسی می کنیم. در الگوی Scatter-Gather که با عنوان پخش کننده - جمع کننده هم شناخته می شود، یک Publisher داریم که پیامی را برروی یک موضوع مشخص، برای تعداد نامعلومی از مصرف کننده (Subscriber) ها منتشر می کند تا بتوانند به طور همزمان به آن پیام دسترسی داشته باشند. در این حالت، فرض بر این است که تمام کسانی که پیام به دستشان میرسد شروع به کار خواهند کرد. و در نتیجه Publisher برای مدت زمانی منتظر پاسخ های رسیده از طرف بعضی یا همه ی Subscriber ها می ماند. سپس به طوری که می خواهد این پاسخ ها را تجمیع کرده و از آنها استفاده می کند.
روش Scatter-Gather چیست؟
روش Scatter-Gather نوعی از سیستم های مدیریت پیام (Messaging System) است که در آن چندین Subscriber داریم و قصد داریم پیامی را برای آنها بفرستیم تا وضعیت شان را به ما گزارش دهند و سپس، از روی پاسخ های بدست آمده از Subscriber هایمان، تصمیمی را بگیریم. در سیستم هایی که scatter-gather را پیاده سازی کرده اند، همیشه یک Publisher و تعداد نامعلومی Subscriber داریم. یکی دیگر از اجزای مهم scatter-gather، ماژول Aggregator یا تجمیع کننده است که وظیفه دارد پاسخ های رسیده را تجمیع کرده و برای تصمیم گیری راحت تر در Publisher آماده کند.
مثال1: فرض کنید یک سایت فروشگاهی هستید که کالای A در فروشگاه شما توسط تامین کننده های متعددی به دست تان می رسد. بعضی از این تامین کننده ها ممکن است این کالا را در انبار خود داشته باشند، بعضی دیگر ممکن است موجودی شان تمام شده باشد. هر تامین کننده قیمت متفاوتی را ارائه می دهد و حتی ممکن است برخی از تامین کننده ها تخفیفی روی آن گذاشته باشند. در نتیجه هر وقت که مشتری ای قصد خرید این کالا را داشت، نیاز است شما آخرین وضعیت این کالا را استعلام گرفته و با شرایط هر یک از تامین کننده ها به مشتری خود نمایش بدهید. در این حالت بهترین الگوی پیاده سازی استفاده از Scatter-Gather است.
مثال2: فرض کنید شما برنامه ی یک تاکسی اینترنتی را نوشته اید، به نظرتان الگوی Scatter-Gather در کدام بخش از معماری و پیاده سازی شما می تواند کمکتان کند؟
روش پیاده سازی Scatter-Gather در NATS
بیایید مانند قسمت های قبلی این کاربرد را هم با مثالی پیش ببریم. فرض کنید چند هزار پهپاد (پرنده ی هدایت پذیر از راه دور - Drone) داریم که ناوگان تحویل بسته های ما را تشکیل می دهند. درخواستی برای تحویل یک بسته رسیده است و حالا باید انتخاب کنیم که از کدام پهپاد برای این کار استفاده کنیم.
با روش های قدیمی اگر می خواستیم این مسئله را حل کنیم، نیاز بود لیستی از پهپادها داشته باشید و این لیست را در یک حلقه (Loop) فراخوانی کنیم و به هر یک از آنها درخواستی ارسال کنیم تا به ما وضعیت شان را اطلاع بدهند (مثلا بگویند چقدر باطری دارند و در چه مسافتی از ما هستند و ...). بعد اطلاعات بدست آمده را جمع کنیم و از روی آنها تصمیم بگیریم که رساندن بسته ی جدید را به کدامیک بسپاریم. همانطور که معلوم است این روش کند است، احتمال بروز خطا در آن خیلی زیاد است و به طور وحشتناکی ناکارآمد خواهد بود.
برای غلبه به همین مشکلات و مشکلات متعدد دیگری که در روش سنتی وجود داشت، ما می توانیم از روش Scatter-Gather استفاده کنیم.
همانطور که در مثال زیر می بینید، من می خواهم یک پیام، روی موضوع package.auction منتشر کنم:
PUB package.auction auction.d5e979a1-bf54-4baf-abdc-c91d451898c5.replies (content-length)
{ "pkg_weight": 12.5, "dest_address": {...}, "priority": "A"}
+OK
به این نکته توجه کنید که مانند روش Request/Reply که در قسمت سوم از همین سری آموزش مطرح کردیم، داریم از یک کانال (Subject یا Topic) دریافت پاسخ منحصر به فرد استفاده می کنیم. استفاده از این کانال منحصر به فرد باعث می شود که همه ی پهپادهایی که در ناوگان حمل و نقل ما آماده هستند و این پیام را دریافت می کنند، روی همین کانال به درخواست پاسخ بدهند و پاسخ هایشان به درخواست های دیگر با این درخواست تداخل پیدا نکند.
اگر پهپادی هم پیام را به هر دلیلی دریافت نکند، یا در بازه ی زمانی مورد انتظار ما پاسخی ندهد، معلوم است که کاندیدای خوبی برای قبول این درخواست نخواهد بود.
پیام ها هم به شکل زیر در پاسخ به درخواست ما از طرف پهپادها برمیگردد:
MSG auction.d5e979a1-bf54-4baf-abdc-c91d451898c5.replies 50 (content-length)
{"drone_id":12345,"est_batt_remaining":12.34,"capacity":30, ...}
در نهایت ما می توانیم این پیام های رسیده را تجمیع کرده و بر اساس اینکه هر پهپاد چقدر باطری دارد، در چه موقعیت جغرافیایی هست، بسته با چه حجمی را می تواند حمل کند و بعد از رساندن بسته چقدر از باطری اش می ماند تا به آشیانه برگردد، تصمیم بگیریم که بسته توسط کدامیک حمل شود.
در بخش بعدی که قسمت پایانی آموزش NATS است، وارد کد شده و یک Pub/Sub را با NATS پیاده سازی میکنیم. در قسمت آخر هم همراه من باشید...