Competing-Consumer-Entwurfsmuster

Aus dev.kaibel.net
Version vom 8. November 2025, 13:56 Uhr von PhilKa (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „= Competing-Consumer-Entwurfsmuster = Das '''Competing-Consumer-Entwurfsmuster''' ist ein Architektur- und Integrationsmuster, das zur Lastverteilung und parallelen Verarbeitung von Nachrichten oder Aufgaben in verteilten Systemen eingesetzt wird. Mehrere Consumer greifen dabei auf eine gemeinsame Nachrichtenquelle (z. B. eine Queue) zu. Jede Nachricht wird genau von einem Consumer verarbeitet, wodurch sich die Last automatisch verteilt und das System…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Competing-Consumer-Entwurfsmuster

Das Competing-Consumer-Entwurfsmuster ist ein Architektur- und Integrationsmuster, das zur Lastverteilung und parallelen Verarbeitung von Nachrichten oder Aufgaben in verteilten Systemen eingesetzt wird. Mehrere Consumer greifen dabei auf eine gemeinsame Nachrichtenquelle (z. B. eine Queue) zu. Jede Nachricht wird genau von einem Consumer verarbeitet, wodurch sich die Last automatisch verteilt und das System horizontal skaliert.

Ziel

Das Muster wird verwendet, um:

  • **Parallelisierung** der Verarbeitung zu erreichen
  • **Last gleichmäßig zu verteilen**
  • **Durchsatz zu erhöhen**
  • **Skalierbarkeit durch Hinzufügen weiterer Consumer** zu ermöglichen
  • **Fehlertoleranz** zu verbessern (bei Ausfall eines Consumers arbeiten andere weiter)

Grundprinzip

Eine Nachrichtenquelle (häufig eine Queue in einem Message-Broker) speichert Aufgaben oder Nachrichten. Mehrere Consumer abonnieren dieselbe Queue und „konkurrieren“ um eingehende Nachrichten. Der Broker stellt sicher, dass jede Nachricht **nur von einem Consumer** verarbeitet wird.

Grafische Darstellung

                +----------------+
                |    Producer    |
                | (stellt Tasks) |
                +--------+-------+
                         |
                         v
                 +---------------+
                 |    Queue      |
                 | (Warteschlange|
                 +-------+-------+
                         |
        +----------------+----------------+
        |                |                |
        v                v                v
+---------------+ +---------------+ +---------------+
|   Consumer 1  | |   Consumer 2  | |   Consumer 3  |
| (verarbeitet) | | (verarbeitet) | | (verarbeitet) |
+---------------+ +---------------+ +---------------+

Ablauf

1. Der **Producer** erzeugt Nachrichten und legt sie in die **Queue**. 2. Mehrere **Consumer** sind gleichzeitig auf die Queue registriert. 3. Sobald eine Nachricht verfügbar ist, erhält **ein einzelner Consumer** diese zur Verarbeitung. 4. Nach erfolgreicher Verarbeitung bestätigt der Consumer den Erhalt (Ack). 5. Die Queue löscht die Nachricht oder stellt sie anderen Consumer bereit, falls ein Fehler auftritt.

Eigenschaften

  • Die Verarbeitung erfolgt **asynchron**.
  • Die Consumer arbeiten **unabhängig** voneinander.
  • Die Lastverteilung erfolgt **automatisch** durch den Broker.
  • Verarbeitung ist **skalierbar**, indem weitere Consumer hinzugefügt werden.

Einsatzgebiete

Das Muster wird häufig verwendet in:

  • **Microservices-Architekturen**
  • **Event-driven Systems**
  • **Hintergrundverarbeitung (Worker Jobs)**
  • **Verteilten Task-Pipelines**
  • **Message-Brokern** wie RabbitMQ, Kafka, ActiveMQ

Beispiel in RabbitMQ (Pseudocode)

Producer

channel.basic_publish(
    exchange='',
    routing_key='task_queue',
    body='Aufgabe 1'
)

Consumer (mehrfach gestartet)

def callback(ch, method, properties, body):
    print(f"Verarbeite: {body}")
    ch.basic_ack(delivery_tag=method.delivery_tag)

channel.basic_qos(prefetch_count=1)
channel.basic_consume(queue='task_queue', on_message_callback=callback)

channel.start_consuming()

Hiermit arbeiten mehrere Instanzen dieses Consumers parallel.

Vorteile

  • **Erhöhte Performance**: Mehr Consumer → schnellerer Durchsatz
  • **Robustheit**: Ausfall einzelner Consumer beeinträchtigt den Prozess nicht
  • **Dynamische Skalierung**: Consumer können zur Laufzeit hinzugefügt oder entfernt werden
  • **Ressourcenoptimierung**: Jeder Consumer verarbeitet genau eine Nachricht zur Zeit

Nachteile

  • **Keine garantierte Reihenfolge** der Verarbeitung
  • **Zustandsverwaltung schwierig**, wenn Aufgaben voneinander abhängen
  • **Monitoring notwendig**, um Engpässe zu erkennen (z. B. zu viele oder zu wenige Consumer)
  • **Systemkomplexität** steigt, wenn Fehlerbehandlung und Retry-Mechanismen berücksichtigt werden

Best Practices

  • Consumer möglichst **zustandslos** gestalten
  • **Idempotente Verarbeitung** sicherstellen (mehrfache Verarbeitung darf keine Fehler verursachen)
  • Nachrichtengröße gering halten → bessere Performance
  • Monitoring von:
 * Queue-Länge
 * Durchsatz
 * Fehlerrate

Zusammenfassung

Das Competing-Consumer-Entwurfsmuster ermöglicht eine **effiziente, skalierbare und fehlertolerante Verarbeitung** von Aufgaben in verteilten Systemen. Mehrere Consumer konkurrieren um Nachrichten in einer gemeinsamen Queue, wobei jede Nachricht von genau einem Consumer verarbeitet wird. Durch Hinzufügen weiterer Consumer kann die Verarbeitungslast problemlos erhöht werden.

Siehe auch

Weblinks