نحوه عملکرد صف های پیام در سیستم های توزیع شده

از فریادهای شهر گرفته تا نامه های نوشتاری و اکنون برنامه های چت بلادرنگ، بشریت همیشه به دنبال راه های نوآورانه برای برقراری ارتباط بوده است. و ما می توانیم همین را در مورد کامپیوتر بگوییم.
حتی نیاز بیشتری برای اجازه دادن به رایانه ها برای ارتباط با پذیرش روزافزون معماری توزیع شده وجود دارد. این همچنین به این معنی است که هماهنگی و مدیریت ارتباطات بین خدمات کوچکتر پیچیده تر شده است.
اما روشهای مختلفی برای اجازه دادن به سرویسها در یک معماری توزیعشده برای ارتباط در طول سالها تکامل یافته است. ما میتوانیم این الگوهای ارتباطی مختلف را در دو دسته کلی قرار دهیم: حالتهای ارتباطی همزمان و ناهمزمان .
اما بیشتر مرتبط با این مقاله، تحلیل چگونگی استفاده از صف های پیام برای پیاده سازی ارتباطات ناهمزمان در یک سیستم توزیع شده است. و مهمتر از آن، چگونه این می تواند به ما کمک کند تا یک معماری قابل اعتمادتر و مقیاس پذیرتر را درک کنیم.
همزمان، ناهمزمان، صف پیام، سیستم های توزیع شده - همه این اصطلاحات چیست؟
این مقاله به آنها می پردازد و مهمتر از آن، پیوند بین صف های پیام و سیستم های توزیع شده را تحلیل می کند. برای شروع، اجازه دهید به سیر تکامل از یکپارچه به سیستم های توزیع شده نگاه کنیم.
توجه: برای اختصار، این مقاله به جای هم از سیستم های توزیع شده و ریزسرویس ها استفاده می کند.
عصر یکپارچه ها
در روزهای اولیه، سیستم های نرم افزاری نسبتا ساده و کوچک بودند. در نتیجه، آنها به عنوان واحدی که بر روی یک فرآیند واحد اجرا می شود، توسعه یافته و مستقر شدند.
برای مثال، فرض کنید روی برنامهای کار میکردید که احراز هویت، پردازش سفارشها، و در نهایت پرداختها را انجام میدهد. شما میتوانید همه این مؤلفهها و پایگاه داده برنامه را در یک واحد کاملاً جفتشده که بهعنوان یک برنامه کاربردی مستقر میشود، یکپارچه کنید.
با گذشت زمان، با استقبال بیشتر مردم از اینترنت، این برنامه های کاربردی یکپارچه شروع به تجربه انفجاری در تعداد کاربران خود کردند - چیز خوبی است، درست است؟ اما این امر برخی از محدودیت های معماری یکپارچه را آشکار کرد.
محدودیت های معماری یکپارچه
اول، با افزایش تعداد کاربران، توسعه دهندگان متوجه شدند که داشتن یک برنامه کاربردی و پایگاه داده آن بر روی یک دستگاه میزبانی شده، عالی نیست. پایگاه داده به سرعت به منبعی تبدیل شد که حافظه و قدرت محاسباتی سرور را می خورد.
برای حل این مشکل، توسعه دهندگان دریافتند که اگر برنامه و پایگاه داده آن بر روی ماشین های مختلف میزبانی شوند، عالی خواهد بود.
حتی با آن، آنها متوجه شدند که انتقال پایگاه داده به یک ماشین جداگانه کافی نیست. همانطور که کاربران بیشتری از یک برنامه کاربردی استفاده کردند، تقاضا برای منابع محاسباتی ماشین میزبان به همان اندازه افزایش یافت.
با تعامل بیشتر کاربران با یک برنامه، توسعه دهندگان متوجه شدند که دستگاه میزبان به حد خود رسیده است. این تأثیر منفی بر سرعت اجرای درخواست کاربر توسط برنامه monolith داشت. این مشکل تاخیر با افزایش ترافیک کاربر بدتر شد.
برای رفع آن، آنها طرح جدیدی را اتخاذ کردند.
معماری یکپارچه تکراری را وارد کنید
در این الگوی طراحی، همان برنامه یکپارچه روی چندین سرور تکرار میشود - با همه سرورها که در پشت یک متعادل کننده بار پنهان هستند. هر یک از یکپارچهها به یک پایگاه داده متصل میشوند و متعادلکننده بار درخواستها را بهطور بهینه به این نمونهها هدایت میکند تا هیچ یک از نمونهها را تحت تأثیر قرار ندهد.
تکرار یک مونولیت در چندین ماشین باعث بهبود عملکرد شد، اما به چه قیمتی؟
ایجاد تغییرات در یکپارچه با معماری تکراری به کاری تبدیل شد که تمام سازه های یک کابوس را داشت. بیایید برخی از این نکات منفی را مرور کنیم.
مشکلات معماری یکپارچه تکراری
برخی از محدودیت های یکپارچه تکثیر شده عبارتند از، اما نه محدود به:
1. دشواری ارتقا یا نگهداری: به عنوان مثال، تصور کنید باید نحوه پردازش پرداختها را بهروزرسانی کنید—شاید به یک پردازشگر پرداخت دیگر بروید. بهروزرسانیهایی مانند این باید در همه یکپارچههای تکراری منعکس شود.
اساساً، همه کپی ها باید حذف شوند، به روز شوند، آزمایش شوند، و سپس دوباره مستقر شوند. به طور کلی، ایجاد تغییرات یا حفظ یکپارچگی، به طور کلی، بسیار دشوارتر از آن چیزی است که باید باشد، زیرا همه اجزاء به طور محکم به هم متصل هستند.
2. مقیاس افقی ناکارآمد: فراتر از تعمیر و نگهداری و ارتقاء، بله، مقیاس افقی یکپارچه با ایجاد نمونه های تکراری می تواند عملکرد را بهبود بخشد - اما نحوه انجام مقیاس بندی در این مورد بهینه نیست. ببینیم چرا…
به یاد داشته باشید، یکپارچه مجموعه ای از اجزای مختلف است که کارهای متفاوتی را انجام می دهند، اما به عنوان یک فرآیند واحد اجرا می شوند. با مثال قبلی، فرض کنید مونولیت ما دارای اجزای احراز هویت، پردازش سفارش و پرداخت است.
در حال حاضر، در یکپارچه، وجود برخی از مؤلفهها که کار بیشتری انجام میدهند (دریافت و پردازش درخواستهای کاربر) نسبت به سایرین معمول است. برای مثال، در مورد ما، هر کاربری که وارد سیستم میشود یا ثبتنام میکند، سفارش نمیدهد یا هزینه سفارش را پرداخت نمیکند.
اگرچه، در مورد ما، ما آگاه هستیم که این مؤلفه احراز هویت است که باید منابع بیشتری را به آن اختصاص دهیم تا مقیاس کنیم، نمیتوانیم. این به این دلیل است که همه اجزا به یکدیگر گره خورده اند و به عنوان یک واحد کار می کنند، پس ما نمی توانیم به سادگی مؤلفه احراز هویت را حذف کنیم.
به همین دلیل است که برای مقیاس افقی یک مونولیت، باید یک نمونه تکراری از کل برنامه را به جای مقیاسگذاری فقط اجزای مربوطه ایجاد کنیم. این به نوبه خود منجر به فشار غیرضروری می شود که می توان از آن بر منابع محاسباتی ماشین میزبان اجتناب کرد.
خلاصه ای از محدودیت های معماری یکپارچه به طور کلی
در نهایت، به دلیل اینکه تمام اجزای یک مونولیت به طور محکم کوپل شدهاند، اگر یکی از اجزاء معیوب باشد، مستقیماً بر در دسترس بودن قطعات دیگر تأثیر میگذارد. واضح است که با یکپارچهها، ما به سیستمهای شکننده میرسیم.
به طور خلاصه، برنامه های کاربردی یکپارچه دارای محدودیت های زیر هستند:
ایجاد تغییرات جدید در یکپارچه و همچنین حفظ و ارتقاء آن در طول زمان دشوار است
مقیاس بندی یک برنامه یکپارچه معمولاً بهینه نیست
برنامه های یکپارچه انعطاف پذیر نیستند - اگر یک قسمت از سیستم خراب شود، کل سیستم از کار می افتد.
میل به ایجاد یک معماری نرم افزاری که بر کاستی های یکپارچه غلبه کند، عصر میکروسرویس ها را به وجود آورد.
میکروسرویس چیست؟
خوب، توسعه دهندگان تحت فشار محدودیت های چشمگیر یکپارچه، تحلیلی شدند و به تصویر بزرگ بازگشتند. آنها فکر کردند، اگر اجزای یکپارچه را که با هم جفت شده اند به عنوان اجزای مستقل با جفت سست توسعه دهیم، چه؟
این تفکر باعث ایجاد چیزی شد که ما اکنون آن را معماری میکروسرویس می نامیم. برخلاف معماری یکپارچه، معماری میکروسرویس یک برنامه کاربردی را به اجزای کوچکتر و متکی به خود به نام سرویس ها تقسیم می کند.
هر سرویس به طور جداگانه توسعه یافته و مستقر می شود. در نتیجه، هر سرویس در یک فرآیند جداگانه اجرا می شود.
با مثال قبلی، یکپارچه ما به سه سرویس تقسیم می شود: سرویس احراز هویت، سرویس پردازش سفارش، و سرویس پردازش پرداخت، همانطور که در تصویر زیر نشان داده شده است.
حتی اگر این سرویسها اکنون به عنوان اجزای مستقل توسعه یافتهاند، همه آنها با هم کار میکنند و برای دستیابی به یک هدف مشترک با هم ارتباط برقرار میکنند - تضمین اینکه کاربران احراز هویت میتوانند خرید و پرداخت کنند.
اما این سؤال را پیش میآورد: این سرویسها چگونه با یکدیگر ارتباط برقرار میکنند؟
الگوهای ارتباطی در معماری میکروسرویس
به طور کلی، خدمات در معماری میکروسرویس را می توان برای برقراری ارتباط به یکی از دو روش پیکربندی کرد: همزمان یا ناهمزمان.
برای درک این دو الگوی ارتباطی، بیایید مثال قبلی خود را بیشتر دنبال کنیم - سناریویی را تصور کنید که در آن سرویس پردازش سفارش باید جزئیات یک سفارش جدید را به سرویس پردازش پرداخت ارسال کند تا پرداخت پردازش شود.
ارتباط همزمان
فرض کنید ارتباط بین دو سرویس همزمان است. در این صورت، سرویس پردازش سفارش، یک تماس API با سرویس پردازش پرداخت برقرار میکند و سپس قبل از ادامه فرآیند، منتظر پاسخ آن سرویس میماند.
در نتیجه سرویس پردازش سفارش تا زمانی که پاسخ درخواست خود را دریافت نکند مسدود می شود. در حالی که الگوی ارتباط همزمان ساده و مستقیم است، هنگامی که در معماری میکروسرویس مورد استفاده قرار میگیرد دارای اشکالات عمدهای است.
یکی از اهداف میکروسرویس ها ایجاد سرویس های کوچک مستقل است که حتی اگر یک یا چند سرویس از کار افتاده باشند، همچنان عملیاتی می شوند. این به حذف نقاط شکست منفرد کمک می کند.
با این حال، این واقعیت که سرویس پردازش سفارش باید بیکار منتظر پاسخ سرویس پرداخت باشد، سطحی از وابستگی متقابل ایجاد می کند که از استقلال مورد نظر هر سرویس می کاهد.
اگر سرویس پردازش پرداخت با یک شکست غیرمنتظره مواجه شود، سرویس پردازش سفارش نمی تواند درخواست های خود را انجام دهد.
اگر سرویس پردازش سفارش با افزایش ناگهانی ترافیک مواجه شود، سرویس پرداخت را نیز تحت تأثیر قرار می دهد زیرا مستقیماً درخواست های خود را به سرویس پرداخت ارسال می کند.
اگر سرویس پرداخت بیش از حد طول بکشد تا پاسخ دهد، سرویس پردازش سفارش نیز برای ارسال پاسخ به کاربر نهایی بسیار طول می کشد.
چگونه می توان این مشکلات را برطرف کرد؟ ارتباط ناهمزمان برای نجات.
ارتباط ناهمزمان
فرض کنید ارتباط بین دو سرویس ناهمزمان است. در این صورت سرویس پردازش سفارش درخواستی را به سرویس پرداخت آغاز می کند و بدون انتظار پاسخ به اجرای آن ادامه می دهد. در عوض، پاسخ را در زمان دیگری دریافت می کند.
برای ارتباطات ناهمزمان، الگوهای متعددی مانند انتشار/اشتراک، صف پیام و معماری رویداد محور در دسترس هستند.
در اینجا، ما علاقه مندیم که ببینیم چگونه می توان ارتباطات ناهمزمان را در میکروسرویس ها با صف پیام پیاده سازی کرد.
صف پیام چیست؟
صف پیام اساساً هر فناوری است که به عنوان یک بافر از پیام ها عمل می کند - پیام ها را می پذیرد و آنها را به ترتیبی که می رسند ردیف می کند. هنگامی که این پیام ها نیاز به پردازش دارند، دوباره به ترتیبی که می رسند خارج می شوند.
پیام هر داده یا دستورالعملی است که به صف پیام اضافه می شود. با مثال ما، یک پیام جزئیات سفارشی است که می تواند به صف پیام اضافه شود و سپس توسط سرویس پرداخت پردازش شود.
معماری صف پیام ساده است – برنامههایی که تولیدکننده نامیده میشوند پیامها را ایجاد کرده و به صف پیام اضافه میکنند. برنامه های کاربردی دیگری به نام مصرف کنندگان این پیام ها را دریافت کرده و آنها را پردازش می کنند. برخی از نمونههایی از صفهای پیام عبارتند از Apache Kafka ، RabbitMQ ، و LavinMQ و غیره.
ما معمولاً میتوانیم از یک صف پیام استفاده کنیم تا به سرویسهای موجود در یک میکروسرویس اجازه دهیم که به صورت ناهمزمان ارتباط برقرار کنند. اما چگونه، ممکن است بپرسید؟
ارتباط همگام در سیستم های توزیع شده با صف پیام
برای نشان دادن اینکه چگونه یک صف پیام میتواند ارتباطات ناهمزمان را در معماری میکروسرویس تقویت کند، به مثالی که در این مقاله تکرار کردهایم برویم.
به یاد بیاورید که ما اشاره کردیم که سرویس پردازش سفارش میتواند جزئیات سفارشهای جدید را به صورت همزمان از طریق یک تماس API به سرویس پردازش پرداخت ارسال کند. ما می توانیم API همزمان را با یک صف پیام جایگزین کنیم.
در اصل، صف پیام بین دو سرویس قرار می گیرد. در این تنظیمات، سرویس پردازش سفارش به عنوان مصرف کننده ای عمل می کند که پیام ها را تولید و به صف پیام اضافه می کند. سپس سرویس پردازش پرداخت به عنوان مصرف کننده ای عمل می کند که پیام های اضافه شده به صف را پردازش می کند.
ارتباط ناهمزمان در اینجا در این واقعیت ذاتی است که وقتی تولید کننده (در این مورد، سرویس پردازش سفارش) پیامی را به صف پیام اضافه می کند، بدون انتظار برای پاسخ به اجرای آن ادامه می دهد.
سپس مصرفکننده میتواند پیامها را از صف پیامها با سرعت خودش پردازش کند و پاسخی را برای تولیدکننده یا کاربر نهایی ارسال کند.
این یک تغییر شدید از رویکرد همزمان است. نبوغ الگوی ارتباط ناهمزمان با صف های پیام در این واقعیت نهفته است که سرویس ها از هم جدا شده و در نتیجه مستقل می شوند.
اگر سرویس پردازش پرداخت با شکست غیرمنتظرهای مواجه شود، سرویس پردازش سفارش همچنان درخواستها را میپذیرد و آنها را در صف قرار میدهد که گویی هیچ اتفاقی نیفتاده است. درخواستها همیشه در صف وجود دارند و منتظر میمانند تا سرویس پرداخت وقتی دوباره آنلاین شد، آنها را پردازش کند. این منجر به یک معماری قابل اعتماد تر بدون هیچ نقطه شکست می شود
خدمات پردازش سفارش لازم نیست منتظر پاسخ مصرف کننده باشد، کاربران نهایی نیز مجبور نیستند برای مدت طولانی منتظر بمانند - این منجر به بهبود عملکرد و در نتیجه تجربه کاربری بهتر می شود.
اگر سرویس پردازش سفارش افزایش ترافیک را تجربه کند، سرویس پرداخت تحت تأثیر قرار نخواهد گرفت زیرا فقط درخواستها را از صفهای پیام با سرعت خود بازیابی میکند.
این روش دارای مزیت مقیاس پذیری ساده است، زیرا امکان گفت ن صف های بیشتر یا ایجاد نسخه های اضافی از سرویس پردازش پرداخت را برای پردازش سریعتر پیام ها فراهم می کند.
بسته بندی
در این مقاله با معماری یکپارچه و میکروسرویس آشنا شدیم. ما همچنین بر کاوش در مفهوم صف های پیام و نحوه پیاده سازی یک الگوی ارتباطی ناهمزمان در معماری میکروسرویس تمرکز کردیم.
سپس به این موضوع پرداختیم که چگونه اتخاذ الگوی ارتباط ناهمزمان در مقابل رویکرد همزمان میتواند منجر به افزایش عملکرد، قابلیت اطمینان و سهولت مقیاس شود.
ما فقط توانستیم سطح صفهای پیام و آنچه را که میتوان با آنها به دست آورد را خراش داد - برای مثال، استفاده در یک معماری توزیعشده تنها مورد استفاده آنها نیست.
برای اینکه درک خود را از صفهای پیام و موارد استفاده از آنها یک قدم فراتر ببرید، میتوانید این راهنمای مبتدی 7 قسمتی را در مورد صفهای پیام و میکروسرویسها تحلیل کنید.
این راهنما عمیقتر میشود و همچنین شما را در ساخت یک برنامه آزمایشی راهنمایی میکند که معماری میکروسرویس را با یک صف پیام اتخاذ میکند. به این ترتیب، نحوه استفاده از صف پیام در یک معماری توزیع شده را به طور مستقیم مشاهده خواهید کرد.
ارسال نظر