بررسی اصول طراحی سیستمهای Resilient و تأثیر آن بر ویژگیهای کیفی نرمافزار.
در بخشهای پیشین، به بررسی faultها و تأثیر آنها بر ویژگیهای کیفی نرمافزار پرداخته شد. یکی از ویژگیهای کیفی مهم در نرمافزارهای مقیاس بزرگ، resiliency است؛ مفهومی که در سالهای اخیر به دلیل تغییرات ساختاری در معماری نرمافزارها و ظهور تکنولوژیهای جدید مانند cloud computing، اهمیت بیشتری یافته است.
تحولات معماری و نقش Resiliency
در معماریهای سنتی نرمافزارها، ساختارهای monolithic غالب بودند که به شکل یک یا چند instance واحد پیادهسازی میشدند. اما با گسترش استفاده از محاسبات ابری، پروژهها مقیاس بزرگتری پیدا کردند و معماریهای توزیعشده (distributed) جایگزین معماریهای متمرکز شدند. این تغییرات باعث شدند که مفاهیمی چون high-availability و resiliency به یکی از بخشهای مهم طراحی و توسعه نرمافزارهای cloud-ready تبدیل شوند.
تفاوت High-Availability در سیستمهای Monolithic و Cloud-Ready
در سیستمهای سنتی، مباحث high-availability عمدتاً در سطح زیرساخت و با روشهایی مثل replication دیتابیس یا سرورهای اپلیکیشن صورت میگرفت. اما در معماریهای cloud-ready، high-availability به بخشهای داخلی معماری و طراحی نرمافزار نفوذ کرد. هدف این است که اگر یکی از سرویسها دچار اختلال شد، نرمافزار به نحوی عمل کند که این اختلال اثر منفی کمتری داشته باشد و حتی بتواند سرویس مختل شده را به مدار بازگرداند.
اهمیت درک Business Context در طراحی سیستمهای Resilient
یکی از نکات مهم در طراحی سیستمهای resilient، درک Business Context است. چرا که failureها به عنوان بخشی از واقعیت سیستمهای بزرگ شناخته میشوند و در صورتی که رخ دهند، باید در چارچوب اهداف و نیازهای کسبوکار مدیریت شوند. دو معیار مهم در این راستا، Mean Time Between Failures (MTBF) و Mean Time to Recovery (MTTR) هستند. هدف اصلی، کاهش زمان لازم برای بازیابی سیستم از failure یا کاهش اثرات جانبی آن است.
فرآیند شناسایی Failure و نقش Circuit Breaker
برای مقابله با failure، ابتدا باید بتوانیم آن را شناسایی کنیم. در این راستا، دو مفهوم Detection و Recognition مطرح میشوند که معانی متفاوتی دارند. با رخ دادن failure، ابتدا باید آن را recognize کنیم، یعنی ماهیت و محل وقوع آن را مشخص کنیم. سپس فرآیند detection برای شناسایی و واکنش به failure انجام میشود. به عنوان مثال، در مکانیزم Circuit Breaker، failure پیشبینی شده و مکانیزمی برای پاسخ مناسب به آن پیادهسازی میشود.
مدیریت failure از طریق Isolate کردن و تفاوت بین ارتباطات Sync و Async
در طراحی سیستمهای resilient، یکی از اصول کلیدی، ایزولهسازی failure است؛ یعنی محدود کردن تأثیر failureها به بخشهای خاص سیستم. در این رابطه، تفاوت بین رفتارهای Sync و Async اهمیت پیدا میکند. در حالت sync، کامپوننتها به طور مستقیم به هم وابستهاند، در نتیجه failure در یکی از کامپوننتها باعث اختلال در دیگری میشود. اما در ارتباطات async، این وابستگی زمانی وجود ندارد و failure یک کامپوننت ممکن است تأثیر کمتری بر کامپوننتهای دیگر داشته باشد.
در حالت async نیز ممکن است دادهها به روز نباشند، در حالی که در حالت sync دادهها بهروز میمانند و محاسبات خطا کاهش مییابد. در اینجا context و نیازهای خاص سیستم تعیین میکند که بروز بودن دادهها تا چه اندازه اهمیت دارد.
استفاده از Cache و رفتارهای پیشفرض در کاهش اثرات failure
راهحلهایی مانند استفاده از Cache و تعریف رفتارهای پیشفرض میتوانند به کاهش اثرات failure کمک کنند و سیستم را از نظر کارکردی ایزوله نگه دارند.
روشهای Protect مانند Timeout و Circuit Breaker
در برخی موارد، هدف اصلی از پیادهسازی راهحلهای protect، رفع failure نیست بلکه جلوگیری از تشدید آن است. به عنوان مثال، در مکانیزم Timeout، یک کامپوننت تنها تا زمانی معین منتظر پاسخ کامپوننت دیگر میماند و در صورت عدم دریافت پاسخ، از انتظار خارج میشود. در مکانیزم Circuit Breaker نیز، با کنترل جریان ارتباط بین دو کامپوننت و قطع ارتباط در صورت لزوم، از تشدید failure جلوگیری میشود. این مکانیزم بر اساس یک state machine کار میکند که شامل حالات Closed، Open و Half-Open است.
نتیجهگیری
طراحی سیستمهای resilient به عنوان یک رویکرد نوین در توسعه نرمافزارهای مقیاس بزرگ، به تیمهای فنی امکان میدهد که با استفاده از تکنیکهای ایزولهسازی، محافظت و مدیریت خطا، پایداری و دسترسپذیری سیستمها را بهبود دهند. این رویکردها نه تنها به کاهش اثرات failure کمک میکنند، بلکه با کاهش زمان بازیابی، پاسخگویی بهتر به نیازهای کسبوکار را نیز ممکن میسازند.