صف پیام یا Message Queuing یک ارتباط سرویس به سرویس غیرهمزمان است که در معماریهای میکروسرویسی و بدون سرور استفاده میشود. به برنامهها اجازه میدهد تا به جای اتصال مستقیم، با فرستادن پیام به یکدیگر به صورت غیرهمزمان، با هر سرعتی، در هر مکانی و مستقل از یکدیگر در ارتباط باشند. وقتی برنامهی مقصد آفلاین باشد یا در حال حاضر مشغول باشد، Message Queue یک صف موقتی ذخیرهی پیام ایجاد میکند. Message Queue میتواند به شدت باعث برنامهنویسی سادهتر برنامههای decouple شده در کنار افزایش کارآیی، اطمینان و مقیاسپذیری شود. میتوان Message Queue بین برنامهها را معادل ایمیل در بین انسانها در نظر گرفت.
صف لیستی از آیتمهای داده، فرمان یا یک کار است که هر که زودتر وارد این لیست شود، زودتر هم خارج میشود. یک صف پیام شامل پیامهایی است که به یک برنامه ارسال شدهاند. این پیامها میتوانند کارهایی باشند که در انتظار پردازش هستند.
پیام، دادهایست که بین برنامههای ارسالکننده و دریافتکننده منتقل میشود. یک آرایهای از بایتهاست که چندین header هم دارد. این پیام معمولا کوچک است و میتواند در مورد یک کار که باید پردازش شود، کاری تمام شده، درخواست، پاسخ، پیام یک خطا و یا فقط یک پیام متنی باشد.
معماری Message Queue ساده است. یک برنامهی کلاینت تحت عنوان تولیدکننده داریم که پیامها را ایجاد میکند و به Message Queue تحویل میدهد. برنامهی دیگری تحت عنوان مصرفکننده داریم که به صف وصل شده و پیامها را برای پردازش کردنشان دریافت میکند. پیامها تا زمانیکه توسط یک مصرفکننده دریافت شوند ذخیره میشوند. چندین تولیدکننده و مصرفکننده میتوانیم داشته باشیم ولی هر پیام یکبار و توسط یک مصرفکننده مصرف میشود. به همین دلیلی این الگوی پیامرسانی، ارتباط one-to-one یا point-to-point نامیده میشود. اگر لازم باشد یک پیام توسط بیش از یک مصرفکننده مصرف شود به آن پیامرسانی Pub/Sub میگویند. که در ادامه این دو نوع الگوی پیامرسانی را بیشتر شرح خواهیم داد.
در فناوری، سیستمی که پیام را در Message Queue قرار میدهد منتظر جواب آن نیست تا بتواند کار خود را ادامه دهد. در واقع Message Queuing یک پروتکل ارتباطی ناهمگام/غیرهمزمان ایجاد میکند. یک مثال خوب برای فهم بهتر ایمیل است. پس از ارسال ایمیل بلافاصله منتظر جواب آن نیستیم تا کار خود را ادامه دهیم. این باعث ایجاد جداسازی (decoupling) تولیدکننده از مصرفکننده میشود.
میتوان بیش از یک صف داشته باشیم. این صفها توسط مدیر صف مدیریت میشوند. ماهیت فیزیکی یک صف به سیستمعاملی که مدیر صف توسط آن اجرا میشود بستگی دارد.
جداسازی یا decoupling یعنی دو سیستم از هم خبر نداشته و بهم وابسته نباشند. هر سیستمی بتواند بدون اتصال به سیستم دیگر به کار خود ادامه دهد. این سیستم، سیستم خوبی است و نگهداری از آن سادهتر است.
اگر سیستمی نتواند پیام را دریافت کند پیام به صف اضافه میشود و تا زمانیکه پیام را دریافت و مصرف کند دوباره ارسال میشود و زمانیکه سیستم احیا شد میتواند آن را مصرف کند و پیام پس از پردازش حذف میشود. میتوان پیامها را طوری فرستاد که در زمان مشخصی توسط مصرفکننده مصرف شوند. پیامها فقط توسط یک مصرفکننده میتوانند مصرف شوند.
به جای اینکه برنامهی بزرگی توسعه دهید، بخشهای مختلف برنامه را Message Queue بهم متصل کنید. در اینصورت هر قسمت از برنامه جداگانه و به راحتی رشد میکند و میتواند به زبانهای مختلف باشد و توسط تیمهای متفاوتی نگهداری شوند.
در معماری میکروسرویس عملکردهای مختلفی در سرویسهای مختلف وجود دارد که عملکردهای متفاوتی را ارائه میدهند. این سرویسها بهم وابسته هستند تا یک برنامهی کامل را بسازند. بدین ترتیب سرویسها بدون کمک هم نمیتوانند کار کنند. به همین دلیل نیاز داریم تا سرویسها بدون در انتظار هم بودن بهم متصل شوند. Message Queue این امکان را با فراهم ساختن یک صف پیام ایجاد میکند. برای اینکار نیاز به یک message broker داریم (معادل پستچی!) که پیامها را از فرستنده به مقصد درست منتقل میکند.
با استفاده از این فناوری میتوان روابط بین فرآیندها را هم کنترل کرد. فرآیندها یکدیگر را invoke نمیکنند و با قرار دادن پیام در صف باهم ارتباط برقرار میکنند. این روش کنترل پیام باعث نگهداری راحت از سیستم و مقیاسپذیری آن میشود.
فناوری Message Queue میتواند برای جداسازی پردازشهای سنگین و بافر یا دستهای کردن کارها استفاده شود.
فرض کنید که یک سیستم وب دارید که باید دسترسپذیری بالایی داشته باشد و به هر درخواست جدید پاسخ دهد. با داشتن یک صف سرویس پردازش و سرویس وب میتوان این سیستم را به بهترین نحو پیادهسازی کرد. در اینصورت این دو سرویس از هم خبر ندارند و سرویس وب پیام یا همان درخواست را در صف گذاشته و سرویس پردازش آن را برداشته و پردازش میکند. در این صورت اگر مقیاس کار گسترش پیدا کند کافیست گنجایش صف را افزایش دهیم.
one-to-one / point-to-point
یک پیامدر صف قرار داده میشود و یک برنامه آن را دریافت کرده و مصرف میکند. برای اینکار فرستنده باید تمام اطلاعات مقصد را داشته باشد.
Publish/Subscribe
یک کپی از پیام توسط برنامهی منتشرکننده به همهی برنامههای مرتبط ارسال میشود. در این صورت نیازی نیست که فرستنده اطلاعات مقصد را داشته باشد.
RabbitMQ
یک message broker است. این فناوری متنباز Advanced Message Queuing Protocol (AMQP) را پیادهسازی میکند که فیچرهایی مانند صفبندی، مسیریابی، امنیت و غیره دارد. شامل تولیدکننده، مصرفکننده، صف و exchange (امکان مسیریابی برای فرستادن پیامها به مقصد درست) است.
Apache Kafka
این مطلب، بخشی از تمرینهای درس معماری نرمافزار در دانشگاه شهیدبهشتی است.
[1] https://www.cloudamqp.com/blog/what-is-message-queuing.html
[2] https://aws.amazon.com/message-queue/
[4] https://medium.com/must-know-computer-science/system-design-message-queues-245612428a22
[5] https://www.ibm.com/docs/en/ibm-mq/8.0?topic=overview-introduction-message-queuing