System DesignMastery
--Distributed Systems — ডিস্ট্রিবিউটেড সিস্টেম

Circuit Breaker & Resilience

Duration৪৫-৬০ মিনিট
LevelIntermediate
FocusSystem Reliability
001Why It Matters

Resilience কেন শিখতে হবে?

আপনার e-commerce app এ Payment service কাজ করছে না। কিন্তু Payment service down থাকলেই কি পুরো app down হওয়া উচিত? User কি product browse করতে পারবেন না?

Distributed system এ Cascading Failure সবচেয়ে ভয়ানক সমস্যা। একটা service slow হলে সেটা অন্য services কে block করে — সব collapse করে। Circuit Breaker এই cascade থামায়।

Real Incident

Amazon Prime Day 2018 এ প্রথম ঘণ্টায় checkout down ছিল। একটা downstream service timeout করছিল এবং সেই timeout অন্য services কে block করছিল। Circuit Breaker থাকলে এটা prevent করা যেত।

DEFINITION

Circuit Breaker কাজ করে electrical circuit breaker এর মতো। যখন কোনো service এ অনেক বেশি failure হয়, circuit breaker সেই service এ call করা বন্ধ করে দেয় — fast failure দেয়, cascade রোধ করে, fallback response দেয়।

002Circuit Breaker States

তিনটা State — বুঝে রাখুন

STATE 🟢 CLOSED

Normal operation। সব requests pass। Failure count track হচ্ছে। Threshold পার হলে OPEN।

STATE 🔴 OPEN

Circuit broken। কোনো request downstream যাচ্ছে না। Fast fail + fallback। Timeout পরে HALF-OPEN।

STATE 🟡 HALF-OPEN

Test phase। কিছু requests allow। Success → CLOSED। Failure → OPEN আবার।

Typical Thresholds & Fast Fail Benefits

Typical Thresholds

৫ seconds এ ৫০% failure rate → OPEN। ৩০ seconds পর → HALF-OPEN। ৩টা success → CLOSED। এগুলো configurable।

Fast Fail Benefits

OPEN state এ thread waste হয় না। Downstream এ load পড়ে না। User কে instant response দেওয়া যায়। System recover করার সুযোগ পায়।

Stateঅবস্থাপরবর্তী Transition
🟢 CLOSEDNormal — সব requests passFailure threshold exceed → OPEN
🔴 OPENBroken — fast fail, fallbackRecovery timeout পর → HALF-OPEN
🟡 HALF-OPENTesting — probe requestsSuccess → CLOSED | Fail → OPEN
003Resilience Patterns

Circuit Breaker ছাড়াও আরো Patterns

1. Retry Pattern — Transient Failure Handle করুন

Network blip, temporary overload — এই ধরনের transient failure এ একবার fail করলেনই দিয়ে দেওয়া ঠিক না। কয়েকবার try করুন।

Retry Storm Problem

সব clients একসাথে retry করলেন failing service এ আরো বেশি load পড়ে। সমাধান: Exponential Backoff + Jitter — প্রতিটা retry তে wait time বাড়াও (100ms → 200ms → 400ms) এবং random jitter যোগ করুন।

2. Bulkhead Pattern — Isolate করুন

জাহাজের watertight compartment এর মতো। Thread pools, connection pools কে isolate করুন। Payment thread pool full হলেও Search pool available থাকে।

Bulkhead: Isolated Thread Pools

Payment Pool (10 threads)

3/10 busy ✅ — Isolated, safe।

Search Pool (8 threads)

1/8 busy ✅ — Completely unaffected!

3. Timeout Pattern — Forever Block করুন না

Service response এর জন্য কতক্ষণ wait করবেন define করুন। ৩০ seconds thread block করা catastrophic। Typical values: ৫০০ms–২০০০ms। SLA এর ৩x হওয়া উচিত।

4. Fallback Pattern — Graceful Degradation

Service fail করলেন alternative response দিন। Recommendation service down? Popular products দেখাও। Search down? Cached results দেখাও। এটাই graceful degradation।

Netflix Fallback

Recommendation service down → "Popular in your area" দেখায়। User experience maintain হয়। Service recover হলে personalized আবার শুরু।

Amazon Fallback

Review service down → Cached reviews দেখায়। Inventory service slow → Stale stock count দেখায়। Order process চলতে থাকে।

004Code Examples

Practical Code

Python: Circuit Breaker Class

circuit_breaker.py
import time
from enum import Enum

class State(Enum):
    CLOSED = "closed"
    OPEN = "open"
    HALF_OPEN = "half_open"

class CircuitBreaker:
    def __init__(self, failure_threshold=5, recovery_timeout=30):
        self.failure_threshold = failure_threshold
        self.recovery_timeout = recovery_timeout
        self.state = State.CLOSED
        self.failure_count = 0
        self.success_count = 0
        self.last_failure_time = None

    def call(self, func, *args, fallback=None, **kwargs):
        # OPEN state check
        if self.state == State.OPEN:
            if time.time() - self.last_failure_time > self.recovery_timeout:
                self.state = State.HALF_OPEN
                print("🟡 HALF-OPEN: Testing service...")
            else:
                print("🔴 OPEN: Fast fail!")
                return fallback() if fallback else None

        try:
            result = func(*args, **kwargs)
            self._handle_success()
            return result
        except Exception as e:
            self._handle_failure()
            return fallback() if fallback else None

    def _handle_success(self):
        if self.state == State.HALF_OPEN:
            self.success_count += 1
            if self.success_count >= 2:
                self.state = State.CLOSED
                self.failure_count = self.success_count = 0
                print("🟢 CLOSED: Service recovered!")

    def _handle_failure(self):
        self.failure_count += 1
        self.last_failure_time = time.time()
        if self.failure_count >= self.failure_threshold:
            self.state = State.OPEN
            print(f"🔴 OPEN: {self.failure_count} failures!")

# Usage
cb = CircuitBreaker(failure_threshold=3)

def payment_call():
    raise Exception("Payment down!")

def fallback():
    return {"status": "pending", "msg": "Processing soon"}

for i in range(5):
    result = cb.call(payment_call, fallback=fallback)
    print(f"Attempt {i+1}:", result)

Node.js: Retry with Exponential Backoff + Jitter

retry_backoff.js
async function retryWithBackoff(fn, maxRetries = 3, baseDelay = 100) {
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
        try {
            return await fn();
        } catch (err) {
            if (attempt === maxRetries) throw err;
            // Exponential Backoff: 100 → 200 → 400ms
            const delay = baseDelay * Math.pow(2, attempt - 1);
            // Jitter: random 0-100ms extra (prevent thundering herd)
            const jitter = Math.random() * 100;
            console.log(`❌ Attempt ${attempt} failed. Wait ${(delay+jitter).toFixed(0)}ms...`);
            await new Promise(r => setTimeout(r, delay + jitter));
        }
    }
}

// Usage: wrap any async service call
const result = await retryWithBackoff(async () => {
    const res = await fetch('http://payment-service/charge', {
        method: 'POST',
        signal: AbortSignal.timeout(2000)  // 2s timeout
    });
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return res.json();
}, 3, 200);
005Real World

Tools Comparison

Real world এ Circuit Breaker manually implement করতে হয় না — battle-tested libraries ও tools আছে। নিচের table দেখুন কোন language/platform এ কোনটা ব্যবহার করবেন।

ToolLanguageTypeBest For
Resilience4jJavaLibrarySpring Boot microservices (Hystrix replacement)
HystrixJavaLibraryLegacy Netflix stack (deprecated 2018)
Polly.NETLibrary.NET microservices — retry, CB, bulkhead
opossumNode.jsLibraryNode.js service calls
pybreakerPythonLibraryPython microservices
IstioAnyService MeshK8s level — infrastructure, no code change
006Interview Preparation

Common Interview Questions

Q1: Circuit Breaker আর Retry এর পার্থক্য কী?

Retry: Transient failure এ কয়েকবার try করুন। Short-term optimism।
Circuit Breaker: Ongoing failure detect করে fast fail দেয়। Long-term protection।
Best practice: দুটো একসাথে ব্যবহার করুন — Retry + Circuit Breaker।

Q2: Cascading Failure কীভাবে prevent করবেন?

একটা service failure অন্য services কে block করে domino effect হয়। Prevention toolkit: Circuit Breaker (fast fail), Bulkhead (isolation), Timeout (don't wait forever), Fallback (graceful degradation)।

Q3: Fallback এর real example দিন

Spotify recommendation down → Most popular songs। Netflix personalization down → Generic popular content। Payment service timeout → "Will process in background"। Search down → Cached results from 5 minutes ago।

Interview এ এটা বলুন

"Resilience pattern গুলো layered — Timeout দিয়ে শুরু, তারপর Retry with Backoff, তারপর Circuit Breaker, তারপর Fallback। এই চারটা একসাথে থাকলে system কখনো completely down হয় না।" — এটাই senior engineer এর answer।
007Infrastructure Level

Istio দিয়ে Circuit Breaker — Code ছাড়াই

Istio Service Mesh ব্যবহার করলেন application code change ছাড়াই infrastructure level এ Circuit Breaker configure করা যায়। Kubernetes এ DestinationRule YAML এ লিখলেই হয়।

istio-circuit-breaker.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: payment-circuit-breaker
spec:
  host: payment-service
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100        # Max TCP connections
      http:
        http1MaxPendingRequests: 10  # Bulkhead: max pending
        maxRequestsPerConnection: 2
    outlierDetection:
      # Circuit Breaker: 50% error rate → eject
      consecutiveGatewayErrors: 5   # 5 consecutive errors → OPEN
      interval: 10s                 # Check every 10 seconds
      baseEjectionTime: 30s         # OPEN for 30 seconds
      maxEjectionPercent: 100       # Eject all bad instances
      minHealthPercent: 0

Istio এর সুবিধা

Application code change লাগে না। যেকোনো language এ লেখা service এ কাজ করে। Kubernetes এ YAML deploy করলেনই হয়। Language-agnostic circuit breaking।
008Lesson Summary

SUMMARY — আজকে যা শিখলাম

Conceptএক লাইনে
Circuit BreakerFailing service এ fast fail — cascade রোধ করে
CLOSED → OPENFailure threshold exceed করলেন
OPEN → HALF-OPENRecovery timeout পরে probe করে
Retry + BackoffTransient failure handle, retry storm prevent
BulkheadThread pool isolate — একটার failure সব থামায় না
TimeoutForever wait করুন না — ৫০০ms–২s
FallbackGraceful degradation — কিছু দিন, কিছু না থেকে
009Knowledge Check
010Assignments
011Practical Lab