خطا در سیستم توزیعشده اجتنابناپذیر است
در یک سیستم با دهها سرویس، همیشه احتمال دارد یک سرویس موقتاً کند یا از دسترس خارج شود. هدف طراحی مقاوم این نیست که از خطا جلوگیری کنیم (که غیرممکن است)، بلکه این است که سیستم بهشکل هوشمندانه با خطا کنار بیاید و اجازه ندهد یک خرابی کوچک به فاجعهی سراسری تبدیل شود.
Retry (تلاش مجدد) سادهترین الگو است: اگر فراخوانی شکست خورد، دوباره تلاش کنید، معمولاً با تأخیر فزاینده (Exponential Backoff) تا فشار روی سرویس مشکلدار را زیاد نکنید:
import time
def call_with_retry(func, max_attempts=3):
for attempt in range(max_attempts):
try:
return func()
except ConnectionError:
if attempt == max_attempts - 1:
raise
time.sleep(2 ** attempt)
Circuit Breaker: جلوگیری از فشار اضافی روی سرویس بیمار
اما retry بیرویه میتواند وضعیت را بدتر کند: اگر سرویس مقصد واقعاً از کار افتاده باشد، تلاش مجدد مکرر از سوی صدها کلاینت فقط فشار بیشتری به آن وارد میکند. الگوی Circuit Breaker (مبتنی بر مفهوم فیوز برق) این مشکل را حل میکند: اگر تعداد شکستهای متوالی به یک سرویس از حد مشخصی بگذرد، مدار «باز» میشود و برای مدتی همهی فراخوانیها بدون تلاش واقعی، بلافاصله با خطا مواجه میشوند تا به سرویس آسیبدیده فرصت بهبود داده شود؛ پس از مدتی مدار بهصورت آزمایشی «نیمهباز» میشود تا وضعیت را بررسی کند. کتابخانههایی مثل pybreaker در پایتون یا resilience4j در جاوا این الگو را آماده پیادهسازی میکنند و ترکیب آن با Retry و Timeout، ستون فقرات مقاومت هر سیستم میکروسرویس واقعی است.