صفهای پیام (Message Queue) یکی از اجزای حیاتی در هر معماری نرمافزار است که کمک میکند مؤلفههای مختلف به صورت غیر همزمان با یک دیگر صحبت کنند. در این پست در مورد این که صف پیام چیست و چگونه میتوان از آن استفاده کرد بحث میکنیم و تعدادی از ابزارهای پیادهسازی صف پیام از جمله RabbitMQ، Appache Kafka و AWS SQS را بررسی میکنیم.
صفبندی پیام به برنامهها این امکان را میدهد که بتوانند با ارسال پیامهایی به یک دیگر از طریق یک صف، به صورت غیرهمزمان ارتباط برقرار کنند. یک صف پیام (message queue) حافظه موقتی بین فرستنده و گیرنده فراهم میکند تا فرستنده بتواند در زمانی که برنامه مقصد مشغول است یا متصل نیست، بدون وقفه به کار خود ادامه دهد.
صف
صف، لیستی از آیتمهای داده، دستورات یا وظایفی است که به ترتیبی خاص و معمولا به ترتیب درج ذخیره میشوند. صف را میتوان خطی از اشیائی تعریف کرد که به ترتیب شروع از ابتدای خط در انتظار رسیدگی هستند.
پیام
پیام، دادهای است که بین برنامهی فرستنده و گیرنده منتقل میشود. در زمینه صف پیام، پیام میتواند چیزی باشد که به سیستمی میگوید که پردازش وظیفهای را شروع کند، همچنین میتواند شامل اطلاعاتی درباره وظیفه تمام شده یا پیامی ساده از یک وظیفه تکمیل شده باشد.
صف پیام
صف پیام، صفی از پیامهایی است که بین برنامهها فرستاده شده است. این صف شامل ترتیبی از اشیاء کاری است که در انتظار پردازش هستند.
صف پیام نوعی ارتباط سرویس به سرویس ناهمزمان است. پیامها تا زمانی که پردازش یا حذف شوند در یک صف ذخیره میشوند.
از صف پیام در معماریهای میکروسرویس و server-less به منظور جداسازی مؤلفههای مختلف استفاده میشود. صف پیام با عبور پیام بین مؤلفههای مختلف به آنها کمک میکند تا به طور غیرهمزمان با یکدیگر ارتباط برقرار کنند.
صف پیام یک پروتکل ارتباطی غیرهمزمان را فراهم میکند که در آن سیستمی که پیامی را در صف پیام قرار میدهد نیازی به پاسخ فوری برای ادامه پردازش ندارد.
معماری صف پیام
در معماری صف پیام یک برنامه client به نام تولیدکننده و برنامه دیگری به نام مصرفکننده وجود دارد.
تولیدکننده (producer): تولید کننده پیامها را ایجاد کرده و آنها را روی صفهای پیام قرار میدهد.
مصرف کننده (consumer) یا کارگر (worker): مصرفکننده به صف متصل میشود، پیامهایی که باید پردازش شوند را دریافت میکند، آن پیامها را میخواند و اقداماتی انجام میدهد.
پیامهایی که در صف قرار میگیرند تا زمانی که مصرفکننده آنها را پردازش کند در حافظه سیستم ذخیره میشوند. نیازی نیست که تولیدکننده و مصرفکننده پیام به صورت همزمان با صف پیام تعامل کنند.
چندین تولیدکننده و مصرفکننده میتوانند از صف استفاده کنند، اما هر پیام تنها توسط یک مصرف کننده پردازش میشود. اگر لازم باشد که یک پیام توسط بیش از یک مصرفکننده پردازش شود، میتوان صفهای پیام را با پیام رسانی Pub/Sub در الگوی طراحی Fan-out ترکیب کرد.
فرض کنید یک وب سرویس یا API دارید که هر ثانیه تعداد زیادی درخواست دریافت میکند و هر درخواست باید توسط فرآیندی زمان بر پردازش شود. لازم است وب سرویس شما دسترسپذیری بالایی داشته باشد و برای دریافت درخواستهای جدید آمادگی داشته باشد، در نتیجه نباید توسط پردازش درخواستهای دریافت شدهی قبلی قفل شود. در این حالت میتوانید بین وب سرویس و سرویس پردازش یک صف قرار دهید. پیامهای موجود در صف به ترتیب دریافت و مدیریت میشوند. دو فرآیند از یک دیگر جدا میشوند و نیازی به انتظاری برای دیگری نیست. اگر تعداد زیادی درخواست در مدت زمان کوتاهی داشته باشید، سیستم پردازش قادر است در هر صورت همهی آنها را پردازش کند.
در معماری میکروسرویس عملکردهای مختلف در سرویسهای متفاوت تقسیم میشوند. این سرویسها به یک دیگر میپیوندند تا یک برنامه نرمافزاری کامل را تشکیل دهند. در معماری میکروسرویس معمولا وابستگیهای متقابل وجود دارد، به این صورت که هیچ سرویسی نمیتواند بدون کمک گرفتن از سایر سرویسها عملکردهای خود را انجام دهد. در اینجا وجود مکانیزمی ضروری است تا به سرویسها اجازه دهد که بدون مسدود شدن توسط پاسخها با یک دیگر در تماس باشند. صفبندی پیامها این هدف را برآورده میسازد. با به کارگیری صف پیام، سرویسها میتوانند به صورت غیر همزمان پیامها را به یک صف هدایت کنند و از تحویل آنها به مقصد درست اطمینان حاصل کنند.
برای پیادهسازی صف پیام، به یک کارگزار پیام (message broker) نیاز است. کارگزار پیام را میتوان به عنوان یک پستچی در نظر گرفت که پیامها را از فرستنده میگیرد و به مقصد درست تحویل میدهد. RabbitMQ یکی از کاربردی ترین message brokerهاست. Apache Kafka و AWS SQS نیز از سرویسهای محبوب صف پیام هستند.
RabbitMQ
نرمافزار RabbitMQ یک کارگزار پیام open-source ، رایگان و قابل توسعه است. RabbitMQ پروتکل صف پیام پیشرفته AMQP (Advanced Message Queuing Protocol) را پیاده سازی میکند و از طریق یک معماری plug-in گسترش مییابد و از پروتکلهای دیگری مانند پروتکل پیامرسانی متن محور STOMP (Streaming Text Oriented Messaging Protocol) و پروتکل انتقال از راه دور صف پیام MQTT (Message Queuing Telemetry Transport) پشتیبانی میکند.
سرور RabbitMQ به زبان Erlang نوشته شده است و در فریمورک OTP (Open Telecom Platform) پیاده سازی شده است. تکنولوژی Erlang/OTP برای ساخت سیستمهای پایدار، قابل اعتماد، مقاوم در برابر خطا و مقیاس پذیر با قابلیت مدیریت تعداد بسیار بالای عملیاتهای همزمان، مناسب است.
Apache Kafka
Apache Kafka یک پلتفرم استریم رویداد توزیع شده است که قادر است تریلیونها رویداد را در روز مدیریت کند. Kafka در ابتدا به عنوان یک صف پیام رسانی ایجاد شد و به سرعت از صف پیام رسانی به یک پلتفرم استریم رویداد کامل تبدیل شد.
همانطور که اشاره شد Kafka یک پلتفرم استریم رویداد توزیع شده است. برای درک بهتر این تعریف لازم است با مفاهیم استریم (stream) و توزیع شده (distributed) آشنا شویم.
استریم چیست؟ به بیان ساده میتوان گفت استریمها دادههای بی نهایت هستند، دادههایی که هرگز تمام نمیشوند، به طور مداوم در حال رسیدن هستند، و باید به صورت real-time پردازش شوند.
توزیع شده به چه معناست؟ توزیع شده در اینجا به این معناست که Kafkaدر یک خوشه (cluster) کار میکند و هر گره (node) در خوشه Broker نامیده میشود. این Broker ها سرورهایی هستند که Apache Kafka را اجرا میکنند.
بنابراین میتوان گفت که Kafka مجموعهای از ماشینهایی است که با یک دیگر کار میکنند تا بتوانند دادههای بی نهایت را به صورت real‑time پردازش کنند.
AWS SQS
سرویسهای وب آمازون (AWS) سرویس صف پیام SQS (Simple Queue Service) را ارائه کردهاند.
سرویس صف ساده آمازون (SQS) یک سرویس صف پیام کاملا مدیریت شده است که جداسازی و مقیاسبندی میکروسرویسها، سیستمهای توزیع شده و اپلیکیشنهای server‑less را ممکن میسازد. با استفاده از SQS میتوان پیامها را بین مؤلفههای نرمافزاری ارسال، ذخیره و دریافت کرد، بدون این که پیامها از دست بروند یا نیاز باشد سایر سرویسها دردسترس باشند.
سرویس SQS دو نوع صف پیام را ارائه میدهد: Standard queue و FIFO queue.
صف استاندارد (Standard queue): صف استاندارد به عنوان نوع صف پیشفرض در نظر گرفته میشود.
صفهای استاندارد دارای حداکثر throughput میباشند. این نوع از صفها تقریبا از تعداد نامحدودی API call در هر ثانیه، در هر API action (ارسال، دریافت، یا حذف پیام) پشتیبانی میکنند.
صفهای استاندارد از تحویل at‑least‑once پشتیبانی میکنند. با این حال گاهی اوقات، به دلیل معماری توزیع شده که امکان انتقال نامحدود را فراهم میکند، ممکن است بیش از یک نسخه از یک پیام خارج از نظم تحویل داده شود.
صفهای استاندارد مرتبسازی best‑effort را فراهم میکنند که تضمین میکند که پیامها عموما به همان ترتیبی که ارسال میشوند تحویل داده میشوند.
صف FIFO (FIFO queue):
صفهای FIFO (First In First Out) به گونهای طراحی شدهاند که تضمین کنند که پیامها دقیقا یک بار و به ترتیبی که ارسال میشوند، پردازش شوند. صفهای FIFO در مواقعی که ترتیب عملیات و رویدادها حیاتی باشد یا در جایی که موارد تکراری قابل تحمل نباشد، منجر به بهبود پیام رسانی بین اپلیکیشنها میشوند.
این مطلب، بخشی از تمرینهای درس معماری نرمافزار در دانشگاه شهیدبهشتی است
منابع:
https://www.cloudamqp.com/blog/what-is-message-queuing.html
https://medium.com/must-know-computer-science/system-design-message-queues-245612428a22
https://en.wikipedia.org/wiki/RabbitMQ
https://www.erlang-solutions.com/blog/an-introduction-to-rabbitmq-what-is-rabbitmq/
https://hub.docker.com/_/rabbitmq
https://www.confluent.io/what-is-apache-kafka/
https://medium.com/swlh/apache-kafka-what-is-and-how-it-works-e176ab31fcd5