راهنمای سریعی برای درک RabbitMQ

راهنمای سریعی برای درک RabbitMQ

یک راهنمای سریع برای درک RabbitMQ 

در جدیدترین پروژه ای که در آن در حال کار هستم، به صورت تیمی الگوی معماریmicroservice  را برای سیستم انتخاب کردیم. انگیزه ی اصلی انتخاب این الگوی معماری، فائق آمدن بر چالش هایی است که معمولاً در معماری های monolith با آن روبرو می شویم (برای مطالعه ی بیشتر در مورد معماری های microservice و مشکلات مرتبط با معماری monolith می توانید به مقاله ی میکروسرویس چیست؟ در سایت سکان آکادمی مراجعه فرمایید). با این حال، هنگام کار با microservice ها، با مسئله ی ارتباط بین سرویس های مختلف مواجه می شویم؛ چرا که چگونگی ارتباط بین سرویس ها و انتقال پیام بین آن ها، همیشه یک تصمیم مهم در طراحی معماری microservice بوده است. بنابراین به دنبال راهی برای حل این مشکل بر آمدیم.

پس از مطالعه و جستجو، دریافتیم که یکی از راه حل های زیبا برای انتقال پیام بین سرویس ها، message broker (کارگزار پیام) است. 

اما message broker چیست؟ RabbitMQچیست و در کجای این ماجرا قرار دارد؟

 در ادامه سعی می کنیم به این سوال ها پاسخ دهیم.

نکته

به طور کلی، در معماری microservice دو راه برای برقرای ارتباط بین سرویس ها وجود دارد:

  • ارتباط Synchronous (همزمان): در این نوع ارتباط، یک برنامه یا سرویس به طور مستقیم و با استفاده از پروتکل HTTP با برنامه دیگر ارتباط برقرار می کند که نیاز به پاسخ فوری و مستقیم از سرور دارد.
  • ارتباط Asynchronous (غیرهمزمان): در این نوع ارتباط که از مکانیزم publish-subscribe استفاده می شود، نیازی به پاسخ فوری از سرور نیست و پیام ها (درخواست ها) به یک کارگزار پیام (مانند RabbitMQ) ارسال می شوند و سرویس مربوطه آن را گرفته و پردازش می کند.

Message Broker (کارگزار پیام) چیست؟

Message Broker نرم افزاری است که برنامه ها، سیستم ها و سرویس ها را قادر می سازد تا با یکدیگر ارتباط برقرار کرده و تبادل اطلاعات داشته باشند. Message Broker با ترجمه پیام ها به پروتکل های پیام رسان رسمی این کار را انجام می دهد. بنابراین به سرویس های وابسته این امکان را می دهد تا با یکدیگر "صحبت" کنند، حتی اگر به زبان های مختلف نوشته شده باشند. Message Broker پیام های دریافتی را از برنامه فرستنده دریافت می کند و آن ها را برای برنامه گیرنده ارسال می کند. به این ترتیب فرستنده و گیرنده می توانند کاملا مجزا باشند. 

نکته

پیام، اطلاعاتی است که از یک برنامه ی فرستنده برای یک برنامه ی گیرنده ارسال می شود. پیام می تواند سیگنالی برای اطلاع رسانی به یک برنامه برای شروع پردازش یک کار باشد، یا اینکه به یک برنامه درباره اتمام کار برنامه دیگری خبر دهد. پیام همچنین می تواند اطلاعات حیاتی مورد نیاز یک برنامه را برای پردازش همان برنامه در خود نگه دارد.

Message Queuing (صف بندی پیام) چیست؟

همه ی پیام ها توسط یک برنامه ی تولید کننده (Producer)، تولید می شوند و به یک صف پیام، push می شوند. این فرایند به Enqueuingمعروف است. پیام های push شده در این صف باقی می مانند تا زمانی که یک برنامه ی مصرف کننده (Consumer) متصل شده و این پیام ها را واکشی کند. این فرایند به Dequeuing معروف است. هر دو فرایند Enqueue و Dequeue به طور مستقل توسط برنامه های Producer و Consumer انجام می شوند و این امکان را داریم که یک پیام را در انتظار دریافت یک Consumer، در یک صف پیام نگه داریم. بنابراین فرایند push شدن پیام به صف توسط برنامه Producer و مصرف شدن آن توسط برنامه Consumer، به عنوان Message Queueing (صف بندی پیام) شناخته می شود.

فرایند ارسال پیام به RabbitMQ و دریافت پیام از آن

شکل 1 فرایند ارسال پیام به RabbitMQ و دریافت پیام از آن

برای اجرای Message Queueing، یک message broker مانند RabbitMQ گزینه خوبی است و در ادامه به پروتکل هایی که RabbitMQ از آن ها پشتیبانی می کند، به چگونگی جریان پیام در RabbitMQ و همین طور به برخی مفاهیم اساسی آن اشاره خواهیم کرد.

RabbitMQ از کدام پروتکل ها پشتیبانی می کند؟

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

RabbitMQ در اصل برای پشتیبانی از AMQP 0-9-1 توسعه داده شد. AMQP پروتکل اصلی است که توسط این broker پشتیبانی می شود. همه نسخه های این پروتکل کاملاً شبیه به هم هستند (با نسخه های بعدی قسمت های نامشخص یا غیر مفید نسخه های قبلی مرتب می شوند). RabbitMQ تعدادی از افزونه های AMQP 0-9-1 را نیز پشتیبانی می کند. 

یک پروتکل پیام رسان متنی ساده است. اجرای این پروتکل بسیار آسان است. RabbitMQ از STOMP (همه نسخه های فعلی) از طریق یک پلاگین پشتیبانی می کند.

یک پروتکل binary است که به دلیل ارسال پیام سبک در آن معروف است. RabbitMQ از طریق پلاگین از MQTT 3.1 پشتیبانی می کند.

احتمالا با این پروتکل آشنا هستید. این یک پروتکل پیام رسانی نیست، اما افزونه های مدیریتی در RabbitMQ از HTTP برای ارسال و دریافت پیام استفاده می کنند. 

شرکت های زیادی، RabbitMQ را به عنوان یک message broker با اجرای پروتکل AMQP در استفاده می کنند که از میان آن ها می توان به Robinhood، reddit و Stack اشاره کرد.

جریان پیام در RabbitMQ

در RabbitMQ، پیام ها مستقیما به صف publish نمی شوند و ابتدا توسط exchange دریافت می شوند. exchange ها بسته به قوانینی که متناسب با نوع آن ها تعیین شده است (در RabbitMQ چهار نوع exchange مختلف وجود دارد که در ادامه ی همین مقاله اشاره ی مختصری به انواع آن ها خواهیم داشت) ؛ پیام ها را از producer دریافت می کنند و به exchange مشخص شده در پیام تحویل می دهند. سپس exchange، پیام ها را در صف ها توزیع می کند. (قابل بیان است که صف ها در RabbitMQ از روش FIFO (First In, First Out)، پیروی می کنند).

برای ارسال پیام های مناسب به صف های مناسب، از قوانینی به نام binding استفاده می شود. binding لینکی است که برای اتصال صف به exchange ها تنظیم می شود. می توان یک صف را به چندین exchange متصل کرد.

 برای درک بهتر جریان پیام در RabbitMQ به تصویر زیر و توضیحات آن توجه کنید:

۱. تولیدکننده یک پیام را به یک exchange، push می کند. هنگام ایجاد exchange، نوع آن باید مشخص شود.

۲. Exchange پیام را دریافت می کند و اکنون مسئول مسیر دهی به پیام است.

۳. بین exchange و صف باید binding تنظیم شود. در این تصویر exchange به دو صف متفاوت bind شده است. exchange، براساس ویژگی های پیام ها (message attribute)، آن ها را به صف ها مسیردهی می کند.

۴. پیام ها در صف قرار می گیرند تا زمانی که توسط یک consumer، مصرف شوند.

۵. Consumer، پیام ها را پردازش می کند. 
 

شکل 2 فرایند قرار گرفتن یک پیام در صف RabbitMQ و دریافت پیام از آن

Exchange ها و انواع آن ها

Exchange یک درگاه ورود به RabbitMQ برای پیام هاست. در RabbitMQ بسته به نوع exchange، پیام ها در صف های متفاوتی مسیردهی می شوند. در اصل چهار نوع وجود دارد:

  • Direct exchange: پیام ها را بر اساس routing key پیام به صف منتقل می کند. routing key یک ویژگی پیام است که توسط تولید کننده به پیام اضافه می شود. می توانید routing key را به عنوان یک "آدرس" در نظر بگیرید که exchange برای تصمیم گیری در مورد نحوه ی مسیردهی پیام از آن استفاده می کند.
  • در direct exchange، پیام به صف هایی هدایت می شود که binding key آن ها دقیقاً با routing key پیام مطابقت دارد. به عنوان مثال، اگر صفی که binding key آن برابر با pdfprocess است به exchange متصل باشد، پیامی که routing key آن برابر با pdfprocess باشد، به آن صف هدایت می شود.
  • Fanout exchange: یک fanout، پیام های دریافتی را به تمامی صف های متصل، منتقل می کند و توجه ای به routing key ها ندارند.
  • Topic exchange: پیام به صفی ارسال می شود که الگوی binding آن با routing key پیام مطابقت داشته باشد.
  • Routing key باید لیستی از کلمات باشد که با نقطه (.) از هم جدا شده باشند. مانند agreements.us و agreements.eu.stockholm. الگوی مسیردهی ممکن است شامل یک ستاره (*) برای مطابقت یک کلمه در یک موقعیت خاص از routing key باشد (برای مثال الگوی مسیردهی agreements.*.*b.* تنها با routing key ای مطابقت دارد که کلمه اول آن agreements و چهارمین کلمه آن b باشد). علامت پوند (#) مطابقت هیچ یا تعدادی از کلمات را نشان می دهد (برای مثال الگوی مسیردهی agreements.eu.berlin.# با هر routing key که با agreements.eu.berlin شروع شده باشد، مطابقت دارد).
  • Headers exchange: از ویژگی های هدر پیام برای مسیریابی استفاده می کنند.  headers exchange بسیار شبیه به topic exchange است، با این تفاوت که مسیردهی در آن به جای routing key بر اساس مقادیر هدر است. اگر مقدار هدر پیام با مقدار مشخص شده در binding برابر باشد، آن پیام مطابقت دارد.

Message Acknowledgement (تایید پیام):

چه اتفاقی می افتد اگر پیامی نتواند به مصرف کننده برساند؟ این امر ممکن است به دلیل خرابی شبکه یا برنامه رخ دهد. اگر هر یک از این خرابی ها اتفاق بیفتد، سیستم ما می تواند پیام را برای همیشه از دست بدهد.

برای پرداختن به این مسئله، AMQP یک مکانیزم تأیید تحویل (delivery acknowledgement) را در کار دارد. بنابراین یک پیام به طور کامل از یک صف حذف نخواهد شد، مگر اینکه از مصرف کننده تأییدیه مثبت ارسال کنیم. در صورت تأیید منفی، پیام می تواند دوباره برای مصرف کننده ارسال شود یا بسته به تنظیمات پیکربندی تولید کننده هنگام ارسال پیام، پیام را رها کند.

جمع بندی:

RabbitMQ محصولی بسیار کامل و مفید برای ارتباط بین سرویس های مختلف در معماری microservice است. این مقاله تنها مقدمه ای برای RabbitMQ است و ما مفاهیم را در این مقاله ساده بیان کردیم تا نقطه ی عطفی برای شروع حرکت شما باشد. می توانید با مراجعه به سایت RabbitMQ، موضوعات و مفاهیم مرتبط با RabbitMQ را کامل تر بررسی کنید. 

منابع:

https://medium.com/swlh/a-quick-guide-to-understanding-rabbitmq-amqp-ba25fdfe421d

https://www.rabbitmq.com/protocols.html

https://www.cloudamqp.com/blog/part1-rabbitmq-for-beginners-what-is-rabbitmq.html

https://www.cloudamqp.com/blog/part4-rabbitmq-for-beginners-exchanges-routing-keys-bindings.html

https://www.rabbitmq.com/tutorials/amqp-concepts.html

https://www.cloudamqp.com/blog/why-use-rabbitmq-in-a-microservice-architecture.html

نظرات
اگر login نکردی برامون ایمیلت رو بنویس: