Hallo Welt
Hallo Welt
Original Lingva Deutsch
Übersetzung wird vorbereitet...
Dieser Vorgang kann bis zu 60 Sekunden dauern.
Diese Seite wird erstmalig übersetzt und dann für alle Besucher gespeichert.
0%
DE Zurück zu Deutsch
Übersetzung durch Lingva Translate

234 Dokumentationen verfügbar

Wissensdatenbank

Circuit Breaker Pattern

Zuletzt aktualisiert: 20.01.2026 um 11:24 Uhr

Circuit Breaker Pattern

Das Circuit Breaker Pattern verhindert Kaskadenausfälle in verteilten Systemen. Lernen Sie die States, Konfiguration und Implementierung für resiliente Anwendungen.

Das Problem

┌─────────────────────────────────────────────────────────────┐
│                 KASKADEN-AUSFALL                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Service A                Service B              Service C │
│   ┌───────┐                ┌───────┐              ┌───────┐│
│   │       │──── Call ─────►│       │──── Call ───►│  💥   ││
│   │       │                │       │              │ DOWN  ││
│   │       │◄─── Timeout ───│       │◄─── Timeout ─│       ││
│   │       │                │       │              └───────┘│
│   │       │                │  ⏳   │                        │
│   │  ⏳   │                │ Wartet│                        │
│   │ Wartet│                │       │                        │
│   └───────┘                └───────┘                        │
│                                                             │
│   OHNE CIRCUIT BREAKER:                                    │
│   • Threads blockieren beim Warten                         │
│   • Timeouts addieren sich                                 │
│   • Ressourcen werden erschöpft                            │
│   • Ausfall propagiert sich nach oben                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Die Lösung: Circuit Breaker

┌─────────────────────────────────────────────────────────────┐
│                 CIRCUIT BREAKER STATES                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│              ┌─────────────────────────────┐               │
│              │                             │               │
│              ▼                             │               │
│       ┌────────────┐    Failure          │               │
│       │   CLOSED   │    Threshold         │               │
│       │            │    erreicht          │               │
│       │ (Normal)   │─────────────────┐    │               │
│       └────────────┘                 │    │               │
│              ▲                       │    │               │
│              │                       ▼    │               │
│         Success              ┌────────────┐               │
│         Threshold            │    OPEN    │               │
│         erreicht             │            │               │
│              │               │ (Blocked)  │               │
│       ┌────────────┐         └─────┬──────┘               │
│       │ HALF-OPEN  │◄──────────────┘                      │
│       │            │    Nach Timeout                       │
│       │ (Testing)  │                                       │
│       └─────┬──────┘                                       │
│             │                                              │
│             │ Failure                                      │
│             └──────────────────────────────►(zurück OPEN) │
│                                                             │
│   CLOSED:    Requests gehen durch                          │
│   OPEN:      Requests werden sofort abgelehnt (Fail Fast) │
│   HALF-OPEN: Testweise einige Requests durchlassen        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Konfiguration

CIRCUIT BREAKER PARAMETER

┌────────────────────────┬────────────────────────────────────┐
│ failureThreshold       │ Anzahl Fehler bis OPEN (z.B. 5)   │
├────────────────────────┼────────────────────────────────────┤
│ failureRateThreshold   │ Fehler-% bis OPEN (z.B. 50%)      │
├────────────────────────┼────────────────────────────────────┤
│ successThreshold       │ Erfolge bis CLOSED (z.B. 3)       │
├────────────────────────┼────────────────────────────────────┤
│ timeout                │ Request Timeout (z.B. 3s)         │
├────────────────────────┼────────────────────────────────────┤
│ resetTimeout           │ Zeit bis HALF-OPEN (z.B. 30s)     │
├────────────────────────┼────────────────────────────────────┤
│ slidingWindowSize      │ Anzahl Requests für Berechnung    │
└────────────────────────┴────────────────────────────────────┘

Beispiel-Konfiguration:
• 5 Fehler in den letzten 10 Requests → OPEN
• 30 Sekunden warten → HALF-OPEN
• 3 erfolgreiche Requests in HALF-OPEN → CLOSED

JavaScript Implementation

// Einfache Circuit Breaker Klasse

class CircuitBreaker {
    constructor(options = {}) {
        this.failureThreshold = options.failureThreshold || 5;
        this.successThreshold = options.successThreshold || 3;
        this.resetTimeout = options.resetTimeout || 30000;

        this.state = 'CLOSED';
        this.failureCount = 0;
        this.successCount = 0;
        this.lastFailureTime = null;
    }

    async execute(fn) {
        if (this.state === 'OPEN') {
            // Prüfen ob resetTimeout abgelaufen
            if (Date.now() - this.lastFailureTime >= this.resetTimeout) {
                this.state = 'HALF_OPEN';
                console.log('Circuit Breaker: HALF_OPEN');
            } else {
                throw new CircuitBreakerOpenError('Circuit is OPEN');
            }
        }

        try {
            const result = await fn();
            this.onSuccess();
            return result;
        } catch (error) {
            this.onFailure();
            throw error;
        }
    }

    onSuccess() {
        if (this.state === 'HALF_OPEN') {
            this.successCount++;
            if (this.successCount >= this.successThreshold) {
                this.reset();
                console.log('Circuit Breaker: CLOSED');
            }
        } else {
            this.failureCount = 0;  // Reset bei Erfolg
        }
    }

    onFailure() {
        this.failureCount++;
        this.lastFailureTime = Date.now();

        if (this.state === 'HALF_OPEN') {
            this.state = 'OPEN';
            this.successCount = 0;
            console.log('Circuit Breaker: OPEN (from HALF_OPEN)');
        } else if (this.failureCount >= this.failureThreshold) {
            this.state = 'OPEN';
            console.log('Circuit Breaker: OPEN');
        }
    }

    reset() {
        this.state = 'CLOSED';
        this.failureCount = 0;
        this.successCount = 0;
        this.lastFailureTime = null;
    }

    getState() {
        return this.state;
    }
}

class CircuitBreakerOpenError extends Error {
    constructor(message) {
        super(message);
        this.name = 'CircuitBreakerOpenError';
    }
}
// Verwendung

const circuitBreaker = new CircuitBreaker({
    failureThreshold: 5,
    successThreshold: 3,
    resetTimeout: 30000
});

async function fetchUser(userId) {
    return circuitBreaker.execute(async () => {
        const response = await fetch(`http://user-service/users/${userId}`, {
            timeout: 3000
        });

        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }

        return response.json();
    });
}

// Aufruf mit Fallback
async function getUserWithFallback(userId) {
    try {
        return await fetchUser(userId);
    } catch (error) {
        if (error instanceof CircuitBreakerOpenError) {
            console.log('Circuit open, using cached data');
            return getCachedUser(userId);
        }
        throw error;
    }
}

PHP Implementation mit Opossum

// Installation: composer require leocarmo/circuit-breaker-php

use LeoCarmo\CircuitBreaker\CircuitBreaker;

// Circuit Breaker mit Redis Storage
$circuitBreaker = new CircuitBreaker(
    new RedisAdapter($redis, 'user-service'),
    'user-service',
    [
        'timeWindow' => 60,           // Sliding Window (Sekunden)
        'failureRateThreshold' => 50, // 50% Fehlerrate
        'intervalToHalfOpen' => 30,   // Zeit bis HALF-OPEN (Sekunden)
        'minimumRequests' => 10,      // Min. Requests für Berechnung
        'successRateToClose' => 80,   // 80% Erfolg → CLOSED
    ]
);

// Verwendung
public function getUser(int $userId): ?User
{
    if (!$this->circuitBreaker->isAvailable()) {
        // Circuit ist OPEN - Fallback nutzen
        return $this->getCachedUser($userId);
    }

    try {
        $response = $this->httpClient->get("/users/{$userId}");
        $this->circuitBreaker->success();
        return User::fromResponse($response);
    } catch (Exception $e) {
        $this->circuitBreaker->failure();
        throw $e;
    }
}

Resilience4j (Java)

// build.gradle
implementation 'io.github.resilience4j:resilience4j-circuitbreaker:2.0.0'

// Java Configuration
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
    .failureRateThreshold(50)                     // 50% Fehlerrate
    .waitDurationInOpenState(Duration.ofSeconds(30))
    .permittedNumberOfCallsInHalfOpenState(3)
    .slidingWindowSize(10)
    .build();

CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config);
CircuitBreaker circuitBreaker = registry.circuitBreaker("userService");

// Verwendung
Supplier<User> decoratedSupplier = CircuitBreaker
    .decorateSupplier(circuitBreaker, () -> userService.getUser(userId));

Try.ofSupplier(decoratedSupplier)
    .recover(CircuitBreakerOpenException.class, e -> getCachedUser(userId))
    .get();

// Mit Annotations (Spring)
@CircuitBreaker(name = "userService", fallbackMethod = "getCachedUser")
public User getUser(Long userId) {
    return userServiceClient.getUser(userId);
}

public User getCachedUser(Long userId, Exception e) {
    return userCache.get(userId);
}

Polly (.NET)

// NuGet: Polly

// Circuit Breaker Policy
var circuitBreakerPolicy = Policy
    .Handle<HttpRequestException>()
    .Or<TimeoutException>()
    .CircuitBreakerAsync(
        exceptionsAllowedBeforeBreaking: 5,
        durationOfBreak: TimeSpan.FromSeconds(30),
        onBreak: (exception, timespan) => {
            Console.WriteLine($"Circuit opened for {timespan.Seconds}s");
        },
        onReset: () => {
            Console.WriteLine("Circuit closed");
        },
        onHalfOpen: () => {
            Console.WriteLine("Circuit half-open");
        }
    );

// Verwendung
try
{
    var result = await circuitBreakerPolicy.ExecuteAsync(
        async () => await httpClient.GetAsync("/api/users/1")
    );
}
catch (BrokenCircuitException)
{
    // Fallback
    return GetCachedUser(1);
}

// Advanced: Mit Timeout kombiniert
var policy = Policy.WrapAsync(
    Policy.TimeoutAsync(TimeSpan.FromSeconds(3)),
    circuitBreakerPolicy
);

Monitoring

// Circuit Breaker Metriken exportieren

const circuitBreakerMetrics = {
    state: 'closed',           // closed, open, half_open
    totalCalls: 1000,
    successfulCalls: 950,
    failedCalls: 50,
    notPermittedCalls: 0,      // Calls blocked by OPEN circuit
    failureRate: 5.0,          // %
    slowCallRate: 2.0,         // %
    timeInOpenState: 0,        // Sekunden
    lastStateChange: '2024-01-15T10:30:00Z'
};

// Prometheus Metriken
circuit_breaker_state{service="user-service"} 1  // 1=closed, 0=open
circuit_breaker_calls_total{service="user-service",result="success"} 950
circuit_breaker_calls_total{service="user-service",result="failure"} 50
circuit_breaker_failure_rate{service="user-service"} 5.0

// Alerting
ALERT CircuitBreakerOpen
  IF circuit_breaker_state == 0
  FOR 1m
  LABELS { severity = "warning" }
  ANNOTATIONS {
    summary = "Circuit breaker is OPEN",
    description = "Circuit breaker for {{ $labels.service }} is open"
  }

Best Practices

1. FALLBACK STRATEGIEN
   ┌────────────────────────────────────────────────────────┐
   │ • Cached Data zurückgeben                             │
   │ • Default Value zurückgeben                           │
   │ • Alternative Service anfragen                        │
   │ • Graceful Degradation (reduzierte Funktionalität)   │
   └────────────────────────────────────────────────────────┘

2. RICHTIGE SCHWELLWERTE
   ┌────────────────────────────────────────────────────────┐
   │ • Zu niedrig: Circuit öffnet zu früh                  │
   │ • Zu hoch: Schäden bevor Circuit öffnet              │
   │ • Sliding Window für stabilere Berechnung            │
   │ • Minimum Requests bevor Entscheidung                │
   └────────────────────────────────────────────────────────┘

3. KOMBINIEREN MIT ANDEREN PATTERNS
   ┌────────────────────────────────────────────────────────┐
   │ • Retry (innerhalb Circuit Breaker)                   │
   │ • Timeout (vor Circuit Breaker)                       │
   │ • Bulkhead (Ressourcen isolieren)                    │
   │ • Rate Limiting                                       │
   └────────────────────────────────────────────────────────┘

4. MONITORING UND ALERTING
   ┌────────────────────────────────────────────────────────┐
   │ • State-Änderungen loggen                             │
   │ • Metriken exportieren                                │
   │ • Alerts bei OPEN State                               │
   │ • Dashboard für Übersicht                             │
   └────────────────────────────────────────────────────────┘
💡 Zusammenfassung: 1. Circuit Breaker verhindert Kaskadenausfälle
2. Drei States: CLOSED → OPEN → HALF-OPEN
3. Immer Fallback-Strategie implementieren
4. Mit Timeout und Retry kombinieren
5. State-Änderungen monitoren und alerten

Weitere Informationen