یکشنبه , ۲۸ مهر ۱۳۹۸
خرید فالوور اینستاگرام خرید لایک اینستاگرام

طراحی مایکروسرویس واکنشی – بخش دوم؛ معماری واکنشی چیست؟

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

  1. بخش اول – طراحی مایکروسرویس
  2. بخش دوم – سیستم‌های واکنشی
  3. بخش سوم – برنامه نویسی واکنشی
  4. بخش چهارم – مدل بازیگر

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

برای درک بهتر، بیایید آمار استفاده از اینترنت را در بازه‌های مختلف بررسی کنیم. در بازه بین سال‌های ۱۹۹۹-۱۹۹۷ اینترنت حدود ۲۸۰ میلیون کاربر داشت و بانکداری آنلاین در دوران اولیه خود قرار داشت. در بازه ۲۰۰۵-۲۰۰۰ کاربران اینترنت به یک میلیون افزایش یافتند. فیس‌بوک در آن زمان ۵.۵ میلیون کاربر داشت، یوتیوب تازه شروع به کار کرده بود، توییتر وجود نداشت و نتفلیکس هم سیستم پخش ویدئو آنلاین را راه‌اندازی نکرده بود. حال در سال ۲۰۱۸، نزدیک به ۴.۲ بیلیون از اینترنت استفاده می‌کنند و فیس‌بوک ۲.۳ میلیون و توییتر ۶۶ میلیون کاربر فعال دارد!

برای ساخت نرم‌افزاری که بتواند حجم زیادی از درخواست را پاسخگو باشد، باید سوالات زیر را همواره در نظر بگیریم:

چگونه می‌توان نرم‌افزاری ساخت که:

  • بتواند با افزایش کاربران از ۱۰ نفر به ۱۰ میلیون نفر، مقیاس‌پذیر باشد؟
  • کمترین میزان از منابع پردازشی برای پشتیبانی از بار فعلی را مصرف کند؟
  • خطا و خرابی را با کمترین تأثیر بر کاربر تحمل کند؟
  • بتواند به راحتی بین ده‌ها تا هزاران ماشین توزیع شود؟
  • بتواند در هر شرایطی تا حد امکان پایدار و پاسخگو باشد؟

یکی از راه‌های پاسخ به نیازهای بالا، استفاده از معماری واکنشی است که بر اساس اصول واکنشی (Reactive Principles) طراحی شده است و در ادامه به بررسی آن می‌پردازیم.

اصول واکنشی

شرکت‌های بسیاری در حال تلاش برای طراحی و ایجاد الگوهایی مشابه برای ساخت نرم‌افزارهای مناسب و پاسخگو به درخواست‌های زیاد بودند. در نهایت یک الگوی جامع و مشخص برای طراحی سیستم‌های واکنشی توسط چند نفر از افراد سرشناس دنیای کامپیوتر و نرم‌افزار ایجاد شد که بیانیه واکنشی (Reactive Manifesto) نام گرفت.

چهار اصول واکنشی پایه در سیستم‌های واکنشی وجود دارد:

پاسخگو (Responsive)

یک سیستم واکنشی باید تا حد امکان در هر شرایطی به درخواست‌های کاربران در سریع‌ترین زمان ممکن پاسخ دهد و همواره در دسترس باشد. همانطور که در تصویر بالا مشاهده می‌کنید، از دیگر اصول سیستم‌های واکنشی، یک فلش به سمت اصل پاسخگویی کشیده شده است. این بدان معنی است که تمام کارها برای پیاده‌سازی یک سیستم واکنشی، برای رسیدن به هدفِ پاسخگو بودن است. بنابراین، پاسخگو بودن مهم‌ترین اصل در سیستم‌های واکنشی است. سیستم‌هایی که بر اساس این اصول ساخته می‌شوند در کنار پاسخگو بودن، قابل نگه‌داری (Maintainable) و توسعه‌پذیر (Extensible) نیز هستند. اگر بتوان بدون نیاز به سه اصول دیگر یک سیستم کاملاً پاسخگو در همه‌ی شرایط را ایجاد کرد، کار ما تمام شده است و یک سیستم واکنشی تولید شده است اما این عمل امکان‌پذیر نیست.

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

منعطف (Resilient)

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

  • تکثیر (Replication): به اجرای چندین نسخه مشابه از یک مولفه سیستم در مکان‌های مختلف مانند نخ‌، پردازه، گره شبکه و یا دیتاسنترهای مختلف را تکثیر می‌نامند. در صورتی‌که یکی از گره‌ها از کار بیافتد، نسخه‌های دیگر از همان مولفه‌ی از کار افتاده که در مکانی دیگر در حال اجرا هستند جای آن را می‌گیرند و سیستم از کار نمیافتد. با استفاده از تکثیر می‌توان به مقیاس‌پذیری با توزیع بار کاری بر روی نسخه‌های مختلف نیز دست یافت
  • انزوا (Isolation): انزوا با “جداسازی” به دست می‌آید. جداسازی یعنی هر مولفه‌ی سیستم باید تنها مبتنی بر خود باشد و تا حد امکان وابستگی به دیگر اجزاء سیستم نداشته باشد. جداسازی می‌تواند در زمان و فضا باشد. یکی از روش‌های دست‌یابی به انزوا، استفاده از اصل مبتنی بر پیام است که با استفاده از آن، فرستنده و گیرنده از یکدیگر جدا هستند و به دلیل ناهمگام بودن ارتباط، نیازی به حضور هر دو در لحظه ارتباط نیست (جداسازی زمان). جداسازی مکان بدین معنی است که فرستنده و گیرنده در یک مکان مشترک نباشد تا در صورت رخدادن خرابی، هر دو با هم از دسترس خارج نشوند. انزوا شبیه اصل هم‌بستگی بالا در طراحی مایکروسرویس‌ها است که در بخش یک به توضیح آن پرداختیم.
  • محدودسازی (Containment): محدودسازی در اصل نتیجه‌ی منزوی سازی است. اگر مولفه‌ها را از یکدیگر منزوی کرده باشیم، خطا یا خرابی به دیگر مولفه‌های سیستم انتشار پیدا نمی‌کند.
  • واگذاری (Delegation): در واگذاری، مولفه یک وظیفه (Task) را برای اجرا به یک مولفه‌ی دیگر واگذار می‌کند و بر اجرای آن وظیفه نظارت می‌کند. اجرای وظیفه می‌تواند در یک نخ، پردازه، گره شبکه و یا دیتاسنتری جدا از ناظر باشد. از مزایای واگذاری این است که واگذارکننده می‌تواند حین اجرای وظیفه توسط مولفه‌ی دیگر به انجام کارهای دیگر بپردازد. همچنین بر اجرای وظیفه نظارت داشته باشد و در صورت رخدادن خطا یا خرابی، بتواند وظیفه را به مولفه‌ی دیگری واگذار کند و یا عملیات‌های دیگر تحمل‌پذیری خطا را انجام دهد.

کشسان (Elastic)

یک سیستم واکنشی با وجود تغییرات در بار کاری (Workload) و تعداد درخواست‌ها، باید در صورت امکان تنها به اندازه نیازِ همان لحظه منابع پردازشی استفاده کند و همچنان پاسخگو بماند. هدف اصلی، ایجاد سیستمی است که جلوی ایجاد تنگراه (Bottleneck) مرکزی و غیر قابل مقیاس‌پذیر گرفته شود و از رقابت بر سر منابع پردازشی به دلیل حجم زیاد درخواست‌ها و وظایف (Resource Contention) اتفاق نیافتد.

به فرایندی که سیستم با بار کاری متغیر همواره خودش را تطبیق دهد و در هر شرایطی بصورت بهینه از منابع پردازشی استفاده کند، قابلیت کشسانی گفته می‌شود. در شرایطی که تعداد درخواست‌ها بسیار بالاست، سیستم به منابع پردازشی خود می‌افزاید تا بتواند این میزان بار کاری را تحمل کند و همچنین در صورتی‌که بار کاری کاهش یابد، سیستم نیز منابع پردازشی خود را آزاد و یا خاموش می‌کند تا هزینه کمتری مصرف شود. قابلیت کشسانی در سامانه‌های ابری که از پرداخت به اندازه استفاده (pay-per-use و یا pay-as-you-go) استفاده می‌کند استفاده می‌شود. 

در نسخه قبلی بیانیه واکنشی، به جای قابلیت کشسانی از کلمه مقیاس‌پذیری (Scalability) استفاده شده بود اما در نهایت به کشسان تغییر پیدا کرد زیرا مقیاس‌پذیری و قابلیت کشسانی تفاوت‌هایی باهم دارند. قابلیت کشسانی بر روی قابلیت مقیاس‌پذیری ساخته می‌شود. در صورتی که مقیاس‌پذیری را خودکارسازی کنیم و این فرایند را بصورت بهینه (استفاده بهینه از منابع پردازشی تا حد امکان) انجام دهیم، به قابلیت کشسانی دست پیدا می‌کنیم.

قابلیت کشسانی انواع مختلفی دارد که یکی از آن‌ها استفاده از روش‌های پیش‌بینی بار کاری است. به عنوان مثال با توجه به رویکردهای مختلف هوش مصنوعی می‌توان تکنیکی پیاده کرد که میزان بار کاری و تعداد درخواست‌ها را در آینده پیش‌بینی کند و زودتر از موعد عملیات مقیاس‌پذیری را انجام دهد. با اینکار قبل از آنکه سیستم با مشکل کمبود منابع پردازشی مواجه شود، تعداد منابع افزایش می‌یابند.

مبتنی بر پیام (Message Driven)

برای پیاده‌سازی تمام اصول گفته‌شده در بالا نیازمند استفاده از معماری مبتنی بر پیام هستیم. یک سیستم واکنشی بر روی پایه و اساس مفاهیم ناهمگام (Async) و پیام‌های غیرمسدود کننده (Non-blocking Message) ساخته می‌شود تا به اتصال سست (Loose Coupling)، انزوا و شفافیت مکان (Location Transparency) دست پیدا کند.

زمانیکه یک مولفه پیامی را به مولفه‌ای دیگر ارسال کند، اگر از روش پیام مسدود کننده استفاده شود، مولفه ارسال‌کننده تا زمان دریافت جواب متوقف می‌شود و هیچ فعالیت دیگری را نمی‌تواند انجام دهد و منابع پردازشی را درگیر خود می‌کند و نمی‌توان از منابع برای کارهای دیگر استفاده کرد که این مغایر با هدف اصلی سیستم‌های واکنشی (استفاده حداکثری از منابع و همواره پاسخگو بودن) است. ممکن است آن مولفه تا ابد منتظر بماند و هیچگاه جواب را دریافت نکند. اما در روش پیام غیرمسدود کننده مولفه بعد از ارسال پیام می‌تواند به بقیه درخواست‌ها پاسخ دهد و وظایف دیگر را انجام دهد و سپس هرگاه جواب را دریافت کرد به پردازش جواب بپردازد. بنابراین بر خلاف روش مسدودکننده که هنگام منتظر ماندن برای جواب نیز از منابع پردازشی استفاده می‌کند، در این روش تنها در زمان پردازش جواب از منابع استفاده می‌شود. در روش غیرمسدود کننده باید از صف پیام استفاده کرد. پیام‌های ارسال شده ابتدا باید در یک صف قرار گیرند و دریافت‌کننده، پیام‌ها را از صف بر می‌دارد و پردازش می‌کند. این صف می‌تواند بصورت یک ماژول جدا بین ارسال‎کننده و دریافت‌کننده قرار بگیرد و یا داخل گیرنده باشد.

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

یکی دیگر از مزایای استفاده از پیام غیرمسدود کننده و اتصال سست، استفاده از قابلیت فشار پشتی (Back-pressure) است. زمانی‌که ارسال کننده پیام‌ها را با نرخی بالاتر از قدرت پردازشی دریافت‌کننده ارسال کند، صف پیام بین آن‌ها به مرور پر می‌شود و پیام‌های جدید را دور می‌ریزد. برای جلوگیری از دور ریخته شدن پیام‌ها، زمانی‌که یک مولفه دریافت کننده نمی‌تواند پا به پای ارسال‌کننده پردازش کند، ارسال‌کننده باید سرعت ارسال خود را کاهش دهد تا باعث رخدادن خطا در دریافت‎کننده و یا از دست رفتن پیام‌ها نشود. در صورتی‌که ارسال و دریافت پیام‌ها بصورت زنجیروار از چندین مولفه عبور می‌کند، سرعت همه‌ی آن‌ها با مولفه‌ی کند باید تنظیم شود.

‌نتیجه‌گیری

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

 

درباره ی سینا نوریان

Avatar
کارشناسی ارشد نرم‌افزار از دانشگاه علم و صنعت ایران، برنامه‌نویس ارشد شرکت فناوران دانشگر. علاقه‌مند به سیستم‌های توزیع شده، معماری‌های مایکروسرویس و واکنشی، پردازش موازی و داده‌های جریانی. زبان‌های مورد علاقه: Scala, Go, Java

دیدگاه بگذارید

avatar
  مشترک شدن  
اطلاع‌رسانی