هانیه محمدی ارزنق
هانیه محمدی ارزنق
خواندن ۹ دقیقه·۳ سال پیش

صف پیام(Message Queue)چیست؟

مقدمه

در مدل Client/Server برای ارتباط بین Client و Server معمولا از روش Request/Response استفاده می‌کنیم؛یعنی Client نیاز خود را در قالب یک Request برای Server ارسال می‌کند و منتظر Response از سمت Server می‌ماند.تا زمانی که Server پاسخ مورد نیاز Client را آماده کند،Client باید منتظر بماند و در صورتی که Server زمان زیادی را نیاز داشته باشد تا پاسخ را آماده کند،در صورت همگام بودن(Synchronous) بودن Request و Response احتمالا Client مسدود(Block) می‌شود.به طور کلی اینترنت بر پایه‌ی این مدل سنتی Request/Response کار می‌کند و در اکثر مواقع مشکلی وجود ندارد و درخواست Client به شکل مناسبی پاسخ داده می‌شود.

مدل سنتی ارتباط بین Client و Server
مدل سنتی ارتباط بین Client و Server


چه زمانی نباید از مدل Request/Response سنتی استفاده کرد؟

۱) فرض کنید آماده شدن Response از طرف Server زمانی نسبتا طولانی نیاز داشته‌باشد و چندین Client به طور مداوم Request‌های خود را برای Server ارسال می‌کنند.در این سناریو Server همیشه باید در دسترس باشد و علاوه بر آن هیچ یک از Request ها نباید از دست بروند.آیا مدل سنتی Request/Response می‌تواند برای این سناریو مناسب باشد؟آیا می‌تواند تجربه کاربری مناسبی را برای کاربران فراهم کند؟

۲) زمانی که از معماری Microservice استفاده می‌کنیم و Client برای گرفتن پاسخ‌نهایی خود نیاز به تعامل چندین سرویس‌ با هم دارد،استفاده از مدل سنتی Request/Response باعث مسدود شدن درخواست Client‌های دیگر می‌شود.برای مثال زمانی که می‌خواهیم یک ویدیو را در Youtube آپلود کنیم چندین سرویس مانند Upload Service، Compress Service، Format Service، Notification Service، باید با یکدیگر همکاری کنند تا درخواست آپلود یک ویدیو انجام شود.

ارتباط زنجیره‌ای سرویس‌ها با یکدیگر برای تولید Response
ارتباط زنجیره‌ای سرویس‌ها با یکدیگر برای تولید Response

همانطور که در تصویر میبینیم به دلیل ارتباط زنجیره‌ای که سرویس‌ها با یکدیگر دارند و هر کدام منتظر پاسخ سرویس بعدی برای یک درخواست هستند، درخواست‌های بعدی برای آپلود ویدیو از سمت Client‌های دیگر که شامل تعداد زیادی درخواست است، مسدود می‌شوند و هر Client بدون دریافت هیچ نوع پاسخی باید برای مدت زمانی طولانی منتظر بماند؛این انتظار تجربه کاربری بسیار بدی را برای application ما خواهد داشت.بنابراین روش سنتی Request/Response برای معماری Microservice مناسب نخواهد بود.

چگونه می‌توان این مشکل را برطرف کرد؟

مشکل اصلی در روش Request/Response این است که کاربر ممکن است برای مدت نامعلومی پشت سیستم خود منتظر بماند تا پاسخی دریافت کند؛چطور می‌توانیم یک تجربه‌ی کاربری مناسب‌تری را برای کاربر فراهم کنیم؟
بهتر است زمانی که می‌دانیم فرآیند پاسخ(Response) طولانی خواهد‌بود،درخواست کاربر را در جایی ذخیره کنیم و به وی اطمینان دهیم که درخواستش(Request) دریافت شده و مدتی طول خواهد کشید تا پاسخ (Response) آماده شود و به محض این که پاسخ آماده شود، کاربر را مطلع خواهیم کرد.
در این صورت کاربر می‌تواند به کارهای دیگر خود برسد و نیازی نیست تمام مدت آماده شدن پاسخ منتظر آن بماند بدون آن که بتواند کار دیگری انجام دهد.
چالش اصلی برای ایجاد این تجربه‌ی کاربری می‌تواند نحوه‌ی ذخیره کردن درخواست Client ها باشد.ساده‌ترین روشی که احتمالا به ذهن همه‌ی ما می‌رسد،ایجاد یک صف(Queue)است که درخواست‌ها به ترتیبی که وارد می‌شوند در آن ذخیره شوند.

معرفی صف پیام(Message Queue)

صف پیام (Message Queue) در واقع همان صفی هست که ما برای ذخیره سازی موقت درخواست‌ها می‌خواستیم.در این روش ،Client، پیام(Message) خود را که حاوی درخواست مورد نظرش است به مقصد Message Queue می‌فرستد؛پیام‌های تمامی Client ها می‌تواند در صف‌های متفاوتی به ترتیب زمان ارسال یا اولویتی که برایشان تعیین می‌شود،قرار بگیرند؛ تا زمانی آن پیام توسط Service یا Application دیگری(Consumer) برای خدمت‌دهی از صف برداشته شود،پیام در صف باقی خواهد ماند و بنابراین هیچ یک از پیام‌ها که حاوی درخواست Clientهاست از دست نخواهد رفت.
پاسخ هر پیام می‌تواند پیامی برای یک Service یا Application دیگر باشد مانند مثالی که برای آپلود ویدیو در Youtube گفتیم بنابراین پاسخ هر پیام نیز مستقیما برای Service یا Application یا Client ارسال نمی‌شود بلکه مقصد هر پاسخ باز هم یک Message Queue خواهد بود.
صف بندی پیام‌ها این امکان را می‌دهد که سرویس‌ها و application ها به طور غیر همگام (Asynchronous) با یکدیگر ارتباط داشته باشندچرا که سرویس‌ها و application ها دیگر به طور مستقیم با یکدیگر در اتباط نیستند و از طریق صف پیام به عنوان یک واسط با هم تعامل می‌کنند.
تولید کننده پیام(Producer) پیام خود را در صف قرار می‌دهد بدون آنکه منتظر بماند تا نتیجه‌ی آن را دریافت کند.
یکی از مثال‌هایی که شاید خیلی از افراد به صورت روزمره با آن در ارتباط هستند می‌ تواند ایمیل باشد.وقتی که ایمیلی را به مقصد ایمیلی دیگر ارسال می کنیم،پیامی با مضمون این‌که ایمیل ما ارسال شد به دست ما می‌رسد و بنابراین ما می‌توانیم به دیگر کار‌های خود برسیم.در ارسال ایمیل پیام ما گره(node)های میانی ذخیره می‌شوند و هر زمانی که گره‌ی بعدی آماده بود،به گره‌ی بعدی ارسال می‌شود بنابراین نیازی نیست تمامی گره‌ها در همان لحظه‌ی ارسال ایمیل ما آنلاین باشند و یا ایمیلی که به مقصد آن پیاممان را ارسال کردیم همزمان با ما آنلاین باشد،پیام به صندوق الکترونیکی مقصد می‌رسد و هر زمان کاربر ایمیل خود را باز کند آن را می بیند.
در واقع Message Queue برای ایجاد این نوع ارتباط بین برنامه‌ها ایجاد شده است(Program to Program)

واژه‌هایی که در Message Queue استفاده می‌شوند

Message: پیامی حاوی داده‌های مورد نیاز است که برای یک سرویس یا برنامه برای Message Queue می فرستد. پیام‌ها انواع مختلفی دارند.
Queue:نام مقصدی که هر برنامه پیام‌های خود را برای آن میفرستد. پیام‌ها در صف‌ها جمع‌آوری می‌شوند تا زمانی که یکی از سرویس‌ها یا برنامه‌ها به آن خدمت رسانی کند
Producer:برنامه یا سرویس‌هایی که پیام‌ها را تولید می کنند و به آن ها اولویت اجرا می‌دهند و درون صف‌ها قرار می‌دهند.
Consumer: سرویس‌ها و برنامه‌هایی که پیام‌ها را از صف بر‌می دارند و به آن‌ها خدمت رسانی می کنند.

انواع Message Queue

  • نقطه به نقطه(Point to Point):یک پیام در صف گذاشته می‌شود و یک برنامه یا سرویس آن را بر‌می‌دارد.در این نوع برنامه‌ای که می‌خواهد پیامی را در صف بگذارد باید درباره‌ی برنامه‌ای که قرار است پیام‌ را دریافت کند اطلاعاتی داشته باشد.برای مثال باید بداند که پیام خود را به کدام صف باید بفرستد و ممکن است نیاز باشد نام Queue Manager مورد نظر را هم درج کند.در این روش در صورتی که پیامی از صف برداشته شود،آن پیام از صف حذف می‌شود و هیچ برنامه‌ی دیگری نمی‌تواند از آن پیام استفاده کند.
  • Publish/Subscribe: در این روش یک کپی از پیام منتشر شده توسط تولید کنندگان(Publisher) به دست مصرف کنندگانی که ذینفع دریافت این پیام‌ها هستند می‌رسد.ممکن است تعداد زیادی،یکی و یا هیچ برنامه‌ی ذینفعی برای دریافت پیام وجود نداشته باشد. در این روش یک برنامه‌ی ذینفع به عنوان Subscriber شناخته می‌شود و پیام‌ها در صف‌های مرتبط با Subscriber ها می‌نشینند. در این روش نیازی به حذف پیام‌ها از صف وجود ندارد

مزایای استفاده از Message Queue

  • کاهش وابستگی میان سرویس‌ها مختلف(Decoupling):با استفاده از Message Queue هیچ یک از سرویس‌ها و application ها در تعامل مستقیم با یکدیگر نخواهند بود،بنابراین نیازی نیست که از نحوه‌ی پیاده‌سازی یکدیگر آگاهی داشته باشند،Producer ها و Consumer ها می‌توانند به زبان‌های مختلفی نوشته شده باشند ، در بستر‌های متفاوتی قرار داشته باشند و،توسعه دهندگان متفاوتی داشته باشند و حتی از Protocol‌های ارتباطی متفاوتی استفاده کنند،اما با استفاده از Message Queue با یکدیگر در ارتباط باشند.بنابراین در صورت تغییر هر یک از سرویس‌ها دغدغه‌ی تغییر در دیگر‌ سرویس‌ها را به وجود نخواهد آورد چرا که وابستگی از لحاظ پیاده‌سازی به یکدیگر ندارند.
  • توسعه پذیری(Scalability): همان‌طور که گفته شد به دلیل کاهش وابستگی میان سرویس‌های مختلف به راحتی می توان سیستم نرم‌افزاری مورد نظر را توسعه داد و ویژگی‌های مختلفی را به آن افزود،در صورتی که می‌خواهیم سرویس دیگری را به سیستم نرم افزاری‌مان اضافه کنیم فقط کافیست با Message Queue ارتباط برقرار کند؛همچنین هر‌ یک از سرویس‌ها را می‌توانیم به شکل‌ دلخواهمان تغییر دهیم.همچین با توسعه‌ی نرم‌افزار می‌توانیم تعداد مصرف کنندگان(Consumer) را افزایش دهیم تا پیام‌ها را با سرعت بیشتری از صف پیام بردارند و پاسخ بدهند.
  • افزایش استفاده‌ی دوباره (Reusability):به دلیل کاهش وابستگی و افزایش توسعه پذیری میان سرویس‌ها در معماری Microservice و Application ها در دیگر معماری‌‌ها، می‌توانیم منطق نرم‌افزار را به بخش‌های کوچک‌تری بشکنیم تا هر بخش تنها مسئول اجرای یک وظیفه باشد.بنابراین Single Responsibility را به شکل دقیق‌تری می‌توانیم پیاده سازی کنیم.به همین دلیل هر یک از بخش‌های نرم‌افزار را می‌توانیم به راحتی برای ساختن نرم‌افزار‌های دیگر به کار ببریم و از این رو سرعت و فرآیندساخت نرم‌افزار‌ها را افزایش دهیم.
  • ارتباط نا‌همگام(Asynchronous Connection):Service‌ها و Application ها نیازی ندارند برای ارتباط با یکدیگر به صورت همزمان آنلاین و در دسترس باشند چرا که صف بندی پیام‌ها این امکان را می‌دهد که پیام‌ها تا زمانی که برای ارائه‌ی خدمت از صف برداشته نشده‌اند،درون صف باقی بمانند؛بنابراین در صورتی که هر یک از سرویس‌ها و یا application‌ها به هر دلیلی در دسترس نبودند یا در حال پردازش پیام دیگری بودند،می توانند در زمان مناسب پیام را از Message Queue بردارند.
  • اولویت‌بندی پیام‌ها(Message Priority):از دیگر مزایای استفاده از یک صف پیام می‌توان به قابلیت اولویت‌بندی پیام‌ها اشاره کرد.زمانی که برنامه می‌خواهد پیامی را در صف پیام قرار دهد،می‌تواند به آن اولویتی اختصاص دهد که این اولویت مشخص کننده‌ی جایگاه آن پیام در صف پیام خواهد بود.

معایب استفاده از Message Queue

اصلی ترین عیب این روش را می‌توان پیچیدگی استفاده‌ از آن دانست چرا که هماهنگی میان Message Queue با هر یک از تولید کنندگان و مصرف کنندگان و چگونگی ارتباط گرفتن صف‌ها با تولید کنندگان و مصرف کنندگان روشی پیچیده را می‌طلبد.اطمینان از این‌که پیامی با محتوای یکسان دو بار ارسال نشده باشد.در روش نقطه به نقطه چگونه می‌توان مطمئن شد که یک پیام توسط یکی از برنامه‌ها خوانده شده تا آن پیام را حذف کنیم تا برنامه یا سرویس دیگری آن را بر ندارد.

معرفی دو ابزار متن باز برای Message Queue

۱) RabbitMQ

RabbitMQ محصول شرکت CloudAMQP است که از طریق پروتکل ارتباطی AMQP پیام‌ها را تبادل می‌کند. نرم افزار RabbitMQ یکی از Message Broker‌های پر استفاده در جهان است، دارای بیش از 35,000 استفاده کننده دارد.RabbitMْQ تمام ویژگی‌های معرفی شده برای Message Queue را دارد و بنابراین با تعریف تنظیمات مورد نیازمان در آن می‌توانیم برای سیستم مورد نظرمان از آن استفاده کنیم و بنابراین نیازی به این نداریم که خودمان یک Message Queue برای سیستم نرم افزاری ایجاد کنیم. با استفاده از RabbitMQ می‌توانیم هر دو نوع Message Queue را پیاده سازی کنیم.
توسعه دهندگان اکثرا این ابزار‌ را به دلیل انعطاف پذیری بالایش در سناریو‌های پیچیده‌ی Routing استفاده می‌کنند. از دیگر قابلیت‌های RabbitMQ می‌توان به نصب پلاگین‌های مختلف بر روی آن برای ساپورت کردن دیگر پروتکل‌های پیام مانند STOMP و MQTT اشاره کرد
این نرم‌افزار با زبان Erlang نوشته شده است و قابلیت نصب بر روی اکثر سیستم عامل‌ها را دارد.

۲)Kafka

Apache Kafka یکی دیگر از Message Broker های معروف و پر استفاده است که LinkedIn آن را با Java و Scala برای پیگیری کردن وبسایت LinkedInتوسعه داده است. استفاده از کافکا نیز می‌تواند مزیت استفاده از هر دو نوع Message Queue را داشته باشد. با توجه به سیستم نرم افزاری مورد نیاز می‌توانیم تنظیمات مورد نظر را برای آن پیاده سازی کنیم.

هر دوی‌ این ابزار‌ها در سطح بالا دارای کارآیی یکسانی هستند اما در جزئیاتی با یکدیگر تفاوت دارند.

شرکت‌هایی که در این زمینه در ایران خدمات ارائه می دهند

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

این مطلب، بخشی از تمرینهای درس معماری نرم‌افزار در دانشگاه شهیدبهشتی است.

منابع

https://www.ibm.com/docs/en/ibm-mq/8.0?topic=overview-introduction-message-queuing

https://www.ibm.com/docs/en/ibm-mq/8.0?topic=queuing-main-features-benefits-message

https://www.ibm.com/docs/en/ibm-mq/8.0?topic=queuing-message-terminology

https://www.cloudamqp.com/blog/what-is-message-queuing.html

https://www.youtube.com/watch?v=DXTHb9TqJOs

https://www.youtube.com/watch?v=5-Rq4-PZlew


معماری_نرم_افزار_بهشتی
شاید از این پست‌ها خوشتان بیاید