كل استدعاء خارجي يحتاج Time Budget
تبدأ المرونة بقبول أن الاعتماديات ستكون بطيئة أو غير متاحة أو نتيجتها ملتبسة. Timeout يحدد مدة الانتظار، وRetry يقرر هل المحاولة الجديدة آمنة، وBackoff يمنع الضغط المتزامن، وCircuit Breaker يوقف الإرسال إلى خدمة تنهار أصلًا. يجب تصميمها مع Idempotency وLatency Budget شامل.
Timeout وRetry وBackoff وCircuit Breaker أدوات مختلفة
- حدد Connect وRequest Timeouts تحت Deadline الكلي للمستدعي.
- أعد فقط الأخطاء المرجح أنها مؤقتة والعمليات المعروفة بأنها Retry-safe.
- استخدم Exponential Backoff مع Jitter بدل الإعادة الفورية الثابتة.
- حدد عدد المحاولات وحجم Retries المتزامنة بميزانية.
- Circuit Breaker يحمي الموارد لكنه يحتاج Fallback أو سلوك Unavailable واضح.
دورة Retry محدودة
يفحص المستدعي Deadline وحالة Circuit، يجرب الخدمة، يصنف الفشل، ينتظر مع Jitter فقط إذا كانت الإعادة آمنة، ويتوقف عند Budget محدود.
Retry محدود مع Backoff وحالة Circuit
يفحص المستدعي Deadline وحالة Circuit، يجرب الخدمة، يصنف الفشل، ينتظر مع Jitter فقط إذا كانت الإعادة آمنة، ويتوقف عند Budget محدود.
جعل مزود غير مستقر قابلًا للتعايش
قيّد المحاولة بDeadline يملكه المستدعي
سياسة Retry الصغيرة يجب أن تصرح بعدد المحاولات والمهلة والأخطاء المؤهلة.
const policy = { attempts: 2, timeoutMs: 600 };
for (let attempt = 1; attempt <= policy.attempts; attempt++) {
try {
return await callProvider({ timeoutMs: policy.timeoutMs });
} catch (error) {
if (!isTransient(error) || attempt === policy.attempts) throw error;
await sleep(withJitter(100 * 2 ** (attempt - 1)));
}
}Retry Storms وأخطاء المرونة
قائمة Resilience
- اكتب Caller Deadline قبل Dependency Timeouts.
- صنف Retryable Errors صراحة.
- اجعل Mutations المعادة Idempotent.
- استخدم Jitter وTotal Retry Budget.
- راقب Timeout Rate وعدد Retries وحالة Circuit وزمن الاعتماد.
