پادیوم بلاگ
معماری رویداد-محور

معماری رویداد-محور: پیاده‌سازی فانکشن Pub/Sub برای ارتباطات ناهم‌زمان

رضا دهقان
تکنولوژی ، مقالات

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

در این پست درباره معماری رویداد-محور (event-driven architecture یا EDA) و رایج‌ترین الگوی پیام‌رسانی در آن، یعنی انتشار/اشتراک (یا pub/sub) صحبت می‌کنیم. در انتهای این پست شما خواهید فهیمد که این  سیستم‌ها چطور می‌کنند، چه چیزی آن‌ها را از متدهای سنتی مجزا می‌کند و چه زمانی باید از آن‌ها استفاده کنید.

معماری رویداد-محور و pub/sub چیست؟

برای درک معماری رویداد-محور و پیام‌رسانی pub/sub باید ابتدا تعاریف آن‌ها را بدانیم:

معماری رویداد-محور

یک مدل طراحی است که سیستم‌های نرم‌افزاری توزیع‌شده را به یکدیگر وصل کرده و امکان ارتباط موثر را فراهم می‌کند. EDA در واقع امکان تبادل داده‌ها در لحظه را ایجاد می‌کند. در طراحی اپلیکیشن‌ها تکیه بر میکروسرویس‌ها (زمانی که هر سرویس پردازش خودش را انجام می‌دهد) رایج است. مفهوم معماری رویداد-محور بیشتر از طریق مدل ارتباطی pub/sub نمود پیدا می‌کند.

pub/sub

یک الگوی پیام‌رسانی منعطف است که به اجزای مختلف سیستم اجازه می‌دهد به صورت ناهم‌زمان با یکدیگر ارتباط برقرار کنند.

نکته اصلی این است که pub/sub به کامپیوترها کمک می‌کند در لحظه به داده‌ها واکنش نشان داده و با یکدیگر ارتباط برقرار کنند. این مدل برعکس مدل سنتی درخواست/پاسخ است که در آن داده در فواصل مختلف و در پاسخ به درخواست کاربر به‌روزرسانی می‌شد. در مدل سنتی همیشه دو مشارکت‌کننده وجود دارد، یک کلاینت و یک سرور. کلاینت روی پروتکل HTTP یک درخواست ارسال می‌کند و سرور محتوای خواسته‌شده را در پاسخ به کلاینت می‌فرستد. به این ترتیب هنگام اتصال سیستم‌های نرم‌افزاری توزیع‌شده بر پایه مدل درخواست/پاسخ همیشه زمان انتظار وجود دارد. با وجود این که این مدل هنوز هم در بسیاری از سیستم‌ها استفاده می‌شود، اما مدل pub/sub به عنوان یک راهکار برای این مشکل هر روز محبوبیت بیشتری کسب می‌کند.

رویدادها و نوتیفیکیشن‌ها چه هستند؟

در سیستم‌های رویداد-محور اجزاء از طریق تبادل نوتیفیکشن‌ها درباره وقوع یک رویداد با یکدیگر تعامل می‌کنند.

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

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

معماری رویداد-محور و اجزای pub/sub

معماری‌های رویداد-محور به طور معمول از سه جزء اصلی تشکیل شده‌اند:

  • تولیدکننده‌های رویداد: که رویداد را تولید یا شناسایی کرده و به مدیران رویداد انتقال می‌دهند.
  • مدیران رویداد: که به عنوان واسط عمل کرده و مسئولیت فیلتر کردن ناهم‌زمان، پردازش و مسیریابی رویدادها را بر عهده دارند.
  • مصرف‌کنندگان رویداد: که رویداد‌ها را دریافت کرده و بر اساس أن عمل می‌کنند.

سیستم‌های pub/sub از معماری معمول رویداد-محور پیروی می‌کنند اما در نام‌گذاری اجزاء تفاوت‌های جزیی دارند. از دید pub/sub، تولیدکنندگان نوتیفیکیشن‌های رویداد به عنوان ناشران (publishers) و مصرف‌کنندگان رویداد به عنوان مشترکین (subscribers) عمل می‌کنند. اما ایده تعامل بین سیستم‌ها در این دو تفاوتی ندارد. 

واسط ممکن است شامل چندین واسط پیام باشد که که رویدادها را به مشترکین (یا مشتریان) علاقه‌مند منتقل می‌کنند. 

سرویس‌های مشترک با ساخت اشتراک بر اساس فیلترهای گوناگون علاقه خود به دریافت نوتیفیکیشن‌ها را به واسط اطلاع می‌دهند اما مسئولیت تطابق رویداد با علاقه‌مندی سرویس بر عهده واسط است.

در سیستم pub/sub‌ چندین مدل اشتراک وجود دارد اما رایج‌ترین نوع آن، اشتراک بر اساس موضوع است که در آن هر کدام از نوتیفیکشن‌ها یک موضوع دارند. نقش‌های ناشران و مشترکین ثابت نیست و ممکن است بر اساس شرایط یک جزء نقش خود را عوض کرده و یا هردو نقش را با هم ایفا کند. 

در چنین معماری‌هایی، سرویس‌های تولیدکننده رویداد نه از وجود سایر سرویس‌های مصرف‌کننده اطلاع دارند نه به آن‌ها اهمیتی می‌دهند (و برعکس). از این رو و به دلیل امکان اضافه کردن اجزای جدید بدون نیاز به تغییر اجزای موجود، EDA و pub/sub برای ساخت و توسعه محیط‌های پویا بسیار مناسب هستند.

اصول الگوی pub/sub در معماری رویداد-محور

سیستم‌های رویداد-محور چندین ویژگی دارند که آن‌ها را از سایر مدل‌های ارتباطی مجزا می‌کنند:

  • مقیاس‌پذیری: از آن‌جایی که در EDAها یک رویداد ممکن باعث دریافت پاسخ از سیستم‌های مختلف با نیازمندی‌ها و نتایج گوناگون شوند، برای مقیاس‌پذیری خطی بسیار مناسب هستند.
  • اتصال سست: تولیدکنندگان و مصرف‌کنندگان از یکدیگر بی‌خبر هستند. در این معماری همیشه یک واسط وجود دارد که رویداد‌ها را دریافت و پردازش کرده و به سیستم‌های علاقه‌مند ارسال می‌کند. به این ترتیب امکان اتصال سست (Loose coupling) سیستم‌ها و تسریع بهبود، تست و استقرار آن‌ها به وجود می‌آید. همچنین بر خلاف سیستم‌های سنتی، در این معماری اجزا را می‌توان به راحتی اضافه یا کم کرد.
  • رویدادهای ناهم‌زمان: نوتیفیکشن‌های رویداد به صورت ناهم‌زمان و در لحظه اتفاق پخش می‌شوند. به این ترتیب، سرویس می‌تواند رویداد منتشرشده را حتی در صورت در دسترس نبودن استفاده یا پردازش کند. این موضوع هیچ تاثیری روی تولید سرویس ندارد.
  • مقاوت در برابر خطا: به دلیل اتصال سست، بروز خطا در یک سرویس هیچ تاثیری روی کار سایر سرویس‌ها ندارد. 

تمام موارد بالا به کسب‌و‌کارهای گوناگون در اندازه‌ها و بازارهای مختلف اجازه می‌دهد تا با نیازهای مشتریان برای دریافت خدمات در لحظه و محصولات و سرویس‌های شخصی‌سازی‌شده هم‌گام باشند.

حالا با ذکر یک مثال نحوه کار مدل pub/sub را بررسی می‌کنیم.

الگوی pub/sub در معماری رویداد-محور چطور کار می‌کند؟

در تصویر زیر نحوه کار الگوی pub/sub را مشاهده می‌کنید. برای مثال فرض کنید می‌خواهیم از طریق اپلیکیشن یک پیتزا سفارش بدهیم. با این که ممکن است میکروسرویس‌های بیشتری در این فرایند درگیر باشند، ما سه سرویس اصلی را در نظر می‌گیریم:

  • سرویس پروفایل کاربر: که در آن کاربر سفارش را ثبت می‌کند.
  • سرویس تحویل غذا: که زمان تحویل را محاسبه کرده و پیک را مشخص می‌کند.
  • سرویس رستوران: که سفارش پیتزا را گرفته و زمانی که حاضر می‌شود به اپلیکیشن نوتیفیکیشن ارسال می‌کند.

گردش کار این فرایند به شکل زیر است:

  • کاربر از طریق سرویس پروفایل کاربری سفارش پیتزا را ثبت می‌کند. این سرویس داده‌های مختلفی نظیر نام، مکان فعلی، اطلاعات تماس و… دریافت کرده و رویداد سفارش پیتزا را منتشر می‌کند. 
  • سرویس تحویل غذا (مثل اسنپ‌فود) مشترک رویداد سفارش پیتزا می‌شود تا تا بتواند رویداد دریافت پیتزا را منتشر کند.
  • سرویس رستوران که مشترک رویداد دریافت پیتزا شده است، سفارش را انجام داده و رویداد سفارش پیتزا آماده است را منتشر می‌کند. 
  • سرویس تحویل غذا رویدادهای ارسال نزدیک‌ترین پیک و تخمین زمان تحویل را منتشر می‌کند. حالا این سرویس می‌تواند مکان پیک را به طور مداوم نظارت کرده و به کاربر نوتیفیکیشن‌های لازم را بفرستد.

تمام میکروسرویس‌ها از طریق یک واسط پیام‌ٰرسانی سیستم با یکدیگر در ارتباط هستند که این واسط به وسیله پلتفرم‌هایی نظیر Apache Kafka قابل پیاده‌سازی هستند. 

ابزارهای لازم برای اجرای معماری رویداد-محور و pub/sub

پیاده‌سازی منطق تبادل داده بین تولیدکنندگان و مصرف‌کنندگان رویداد از طریق پلتفرم‌های پردازش رویداد قابل انجام است. تصمیم‌گیری انتخاب ابزار به طور معمول بر عهده تیم فنی است تا بر اساس نیازمندی‌ها نرم‌افزار مناسب را انتخاب کند. در ادامه بازگیران اصلی این عرصه را به طور مختصر معرفی می‌کنیم:

Apache Kafka

شاید محبوب‌ترین پلتفرم در دنیای جریان داده‌های توزیع‌شده Apache Kafka باشد. این پلتفرم متن‌باز انتشار، مرتب کردن، پردازش و توانایی پذیرش اشتراک توسط رویدادها را پشتیبانی می‌کند. پلتفرم Kafka فانکش pub/sub را به صورت مقیاس‌پذیر، مقاوم در برابر خطا و امن ارائه داده تریلیون‌ها رویداد را به صورت روزانه انجام می‌دهد. علاوه بر این، پلتفرم Apache Kafka به دو صورت محلی و ابری قابل استقرار است.

Pulsar

یکی دیگر از اعضای خانواده Apache است که قابلیت پیام‌رسانی pub/sub توزیع‌شده را ارائه می‌کند. این پلتفرم که ابتدا به عنوان سیستم صف‌بندی پیام طراحی شده بود، در سال‌های اخیر فانکشن استریم رویداد را نیز اضافه کرده است. این سیسم با جداسازی عملیات‌های تولید و مصرف مدل‌های پیام‌رسانی منعطفی را ارائه کرده و امکان مقیاس‌پذیری در سطوح بالا را فراهم می‌کند.

ActiveMQ

این پلتفرم متن‌باز یک واسط پیام‌رسانی منعطف است که توسط بنیاد نرم‌افزاری آپاچی ارائه شده است. پلتفرم ActiveMQ امکان پیام‌رسانی pub/sub از طریق موضوعات بین تولیدکنندگان و مصرف‌کنندگان مختلف را فراهم می‌کند. استقرار ActiveMQ در ساختارهای پیچیده به نسبت ساده بوده و ثبات بسیار زیادی دارد.

Redis

نیز مانند موارد قبلی به صورت متن‌باز ارائه می‌شود.  این پلتفرم به طور معمول به عنوان یک واسط پیام‌رسانی واسط و پایگاه داده مورد استفاده قرار می‌گیرد. همچنین Redis برای اپلیکیشن‌های pub/sub بسیار محبوب بوده و امکان پردازش میلیون‌ها درخواست را فراهم می‌کند.

البته که موارد بالا تنها بخشی از ابزارهای موجود در این حوزه هستند و ساخت یک معماری رویداد-محور کاربردی نیازمند سرویس‌های مکمل دیگری نظیر ذخیره‌سازی ابری نیز هست.

شرکت‌های کوچک می‌توانند با کمک راهکارهای زیرساخت به عنوان سرویس (IaaS) یا پلتفرم به عنوان سرویس (PaaS) معماری رویداد-محور و فانکشن pub/sub خود را با هزینه معقول پیاده‌سازی کنند؛ اما برای شرکت‌های بزرگ که منابع بیشتری دارند توصیه می‌شود راهکار خود را متناسب با نیازها از پایه توسعه دهند.

کاربردهای معماری رویداد-محور و pub/sub 

از آن‌جایی که اپلیکیشن‌های رویداد-محور به دلیل ارائه داده‌های به‌روز امکان تصمیم‌گیری در لحظه را برای کسب‌و کارها فراهم می‌کنند، کاربردهای زیادی برای آن‌ها وجود دارد که در ادامه به برخی از آن‌ها اشاره می‌کنیم:

  • اینترنت اشیاء: راهکارهای IoT در صنایع مختلفی از جمله سلامت کاربرد دارند. این راهکارها به طور معمول حجم زیادی از داده را ردوبدل می‌کنند. به همین دلیل معماری رویداد-محور می‌توانند با ایجاد امکان انتقال داده‌ها به صورت لحظه‌ای، تصمیم‌گیری لحظه‌ای را ممکن ساخته و کاربردپذیری این راهکارها را توسعه دهند.
  • خرید آنلاین: از آن‌جایی که در پردازش خرید آنلاین سرویس‌های زیادی درگیر هستند، EDA یک راهکار عالی برای برقراری ارتباط بین آن‌ها است. 
  • بانکداری آنلاین: با معماری رویداد-محور امکان نظارت بر تراکنش‌ها در لحظه، شناسایی فعالیت‌های کلاه‌بردارانه و اطلاع این فعالیت‌ها به مشتریان در لحظه برای بانک‌ها فراهم می‌شود.

معماری رویداد-محور یک راهکار عالی است، اما جواب همه سوالات نیست

معماری‌های رویداد-محور برای زمانی مناسب هستند که چابکی، تعامل و اتصال سیستم اولویت به شمار می‌روند. به همین دلیل این معماری را بیشتر می توان در اپلیکیشن‌های مدرنی یافت که از میکروسرویس‌ها و اجزای جدا استفاده می‌کنند.

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