Circuit Breaker und Retry-Strategien in Docker-Umgebungen

In der Welt von Microservices und containerisierten Architekturen gehört eines zur Realität: Fehler passieren. Ein Service ist nicht erreichbar, eine Datenbank antwortet zu langsam oder eine externe API ist überlastet. Die zentrale Frage ist also nicht „ob“, sondern „wann“ Ausfälle auftreten – und wie wir darauf vorbereitet sind.

Zwei essenzielle Muster helfen uns dabei, Anwendungen robuster und widerstandsfähiger zu gestalten:

  • Circuit Breaker (Leistungsschutzschalter)
  • Retry-Strategien (Wiederholungslogik bei Fehlern)

In diesem Artikel erfährst du, wie du diese Patterns in einer Docker-Umgebung umsetzt, welche Tools dir helfen können, und worauf du beim Design achten solltest.

Resilienz in Microservices

1. Warum braucht man Resilienz in Microservices?

Stell dir vor: Dein Service A ruft regelmäßig Service B auf. Plötzlich wird Service B langsam oder fällt ganz aus. Was passiert?

  • Ohne Schutz: Service A wartet ewig → Timeouts → Threads blockiert → Alles stürzt ab.
  • Mit Schutz: Service A erkennt das Problem → bricht frühzeitig ab → umgeht Folgefehler.

Ziel: Fail fast, fail safe. Deine App sollte sich im Problemfall kontrolliert verhalten und nicht „mit ins Verderben stürzen“.


2. Retry-Strategien – Wenn der erste Versuch scheitert

Was ist eine Retry-Strategie?

Eine Retry-Strategie versucht bei einem temporären Fehler (z. B. Timeout, Netzwerkfehler) den Request noch einmal – nach einem definierten Schema.

Beliebte Strategien

  • Fixed Delay Retry
    Versuche den Request z. B. 3× mit je 2 Sekunden Abstand.
  • Exponential Backoff
    Jeder weitere Versuch hat einen doppelt so langen Abstand: 1s, 2s, 4s, …
  • Jitter / Random Backoff
    Vermeidet „Thundering Herd“-Effekte durch Zufallskomponente.

Wann ist Retry sinnvoll?

  • Temporäre Netzwerkfehler
  • Ratenbegrenzung (Rate Limiting)
  • Langsame Antwortzeiten

Wann NICHT retryen?

  • Bei 4xx-Fehlern (z. B. 400, 401, 404)
  • Bei validierten Business-Fehlern
  • Wenn der Zielservice komplett down ist (→ Circuit Breaker!)

3. Circuit Breaker – Der digitale Leistungsschutzschalter

Was ist ein Circuit Breaker?

Ein Circuit Breaker schützt dein System, indem er den Aufruf zu einem fehlerhaften Service vorübergehend unterbricht. Er verhält sich wie ein Stromkreisunterbrecher im Haus:

  • Closed (geschlossen) – Alles läuft normal.
  • Open (offen) – Zu viele Fehler → keine neuen Anfragen durchlassen.
  • Half-Open – Probiert gelegentlich, ob der Dienst wieder stabil ist.

Was bringt das?

  • Verhindert Ressourcenverschwendung bei bekannten Ausfällen
  • Vermeidet Kaskadenfehler in abhängigen Services
  • Unterstützt schnelles Fehler-Feedback

4. Umsetzung in Docker/Microservices

4.1. Retry mit HTTP-Clients (Beispiel: Axios in Node.js)

const axios = require('axios');
const axiosRetry = require('axios-retry');

axiosRetry(axios, {
  retries: 3,
  retryDelay: axiosRetry.exponentialDelay,
  retryCondition: (error) => error.response?.status >= 500
});

axios.get('http://myservice/api/data')
  .then(res => console.log(res.data))
  .catch(err => console.error('Fehler nach Retries:', err.message));

4.2. Circuit Breaker mit resilience4j in Spring Boot

build.gradle:

implementation 'io.github.resilience4j:resilience4j-spring-boot3:2.1.0'

Konfiguration:

resilience4j.circuitbreaker:
instances:
myService:
registerHealthIndicator: true
slidingWindowSize: 10
failureRateThreshold: 50
waitDurationInOpenState: 10s

Service-Aufruf mit Schutz:

@CircuitBreaker(name = "myService", fallbackMethod = "fallback")
public String callRemoteService() {
return restTemplate.getForObject("http://my-service/api", String.class);
}

public String fallback(Throwable t) {
return "Service temporär nicht verfügbar";
}

4.3. Beobachtung mit Prometheus & Grafana

Tools in der wie resilience4j liefern Metriken, die Prometheus scrapen kann – etwa:

  • Anzahl der Retries
  • Circuit Breaker Status
  • Erfolgsraten von Service Calls

Grafana-Panel Ideen:

  • % Open Circuits
  • Retry Rate pro Service
  • Top 5 Services mit Fehlern

5. Integration in Docker-Umgebungen

Die meisten dieser Tools sind bibliotheksbasiert (d.h. du nutzt sie direkt im Anwendungscode), aber du kannst auch auf Proxies oder Sidecars setzen:

Service Meshes wie Istio oder Linkerd

Diese bieten Circuit Breaking, Timeouts, Retries außerhalb deiner App, auf Netzwerkebene. Ideal für Kubernetes.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: myservice
spec:
  host: myservice
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
    outlierDetection:
      consecutiveErrors: 5
      interval: 10s
      baseEjectionTime: 30s

6. Best Practices

  • Timeouts sind Pflicht. Ohne definierte Timeouts sind Retries und Circuit Breaker sinnlos.
  • Fehlertypen klassifizieren. Nicht jeder Fehler ist ein Retry-Kandidat.
  • Monitoring & Logging einbauen. Circuit Breaker ohne Metriken sind blind.
  • Fallbacks definieren. Besser eine degraded Response als ein Total-Ausfall.
  • Kombiniere nicht unüberlegt. Zu viele Retries bei offenen Circuits = Overkill.

Fazit

In einer Microservice- und Docker-Welt ist Resilienz keine Kür, sondern Pflicht. Mit intelligenten Retry-Strategien und Circuit Breakern kannst du deine Services gegen temporäre Ausfälle und Überlastung schützen. Tools wie resilience4j, Istio oder eigene Code-Patterns machen es leicht, diese Schutzmechanismen umzusetzen – und Prometheus & Grafana helfen beim Überblick.


Nächste Schritte

  • Implementiere resilience4j oder eine Retry-Logik in deinen wichtigsten Services.
  • Teste die Fehlerfälle aktiv (z. B. durch gezielte Downtime in Docker Compose).
  • Richte Dashboards ein, um Resilienzmetriken zu überwachen.
  • Überlege dir, ob ein Service Mesh für dich sinnvoll ist.

Links

Docker Umgebungen

Aufbau und Verwaltung von Docker Images

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert