Publisher-Subscriber-Entwurfsmuster
Publisher-Subscriber-Entwurfsmuster
Das Publisher-Subscriber-Entwurfsmuster (kurz: Pub/Sub) ist ein Verhaltens- und Integrationsmuster, das die asynchrone, lose gekoppelte Kommunikation zwischen Softwarekomponenten ermöglicht. Statt dass Sender (Publisher) Nachrichten direkt an Empfänger (Subscriber) senden, werden diese über eine vermittelnde Instanz (z. B. Message Broker oder Event-Bus) verteilt.
Ziel
Das Muster soll:
- Abhängigkeiten zwischen Sender und Empfänger vermeiden
- Asynchrone Kommunikationsabläufe ermöglichen
- Skalierbarkeit verbessern
- Flexibilität und Erweiterbarkeit des Systems erhöhen
- Ereignisgesteuerte Architekturen unterstützen
Grundprinzip
Komponenten, die Nachrichten senden möchten, veröffentlichen diese bei einem Publisher oder über einen Message Broker. Komponenten, die Nachrichten empfangen möchten, registrieren sich (abonnieren) bei einem Subscriber-Interface oder beim Broker. Der Publisher kennt die Subscriber nicht direkt.
Grafische Darstellung
Publisher Subscriber
(Sendet Events) (Empfängt Events)
| ^
| |
v |
+--------- Message Broker --------+
Komponenten
| Komponente | Rolle |
|---|---|
| Publisher | Erzeugt und veröffentlicht Nachrichten/Ereignisse. |
| Subscriber | Registriert sich für bestimmte Nachrichten und verarbeitet sie. |
| Broker / Event Bus | Vermittelt Nachrichten zwischen Publishern und Subscribern. |
Ablauf
1. Der Subscriber meldet sich beim Broker für bestimmte Themen oder Ereignisse an. 2. Der Publisher sendet eine Nachricht an den Broker. 3. Der Broker verteilt die Nachricht automatisch an alle relevanten Subscriber. 4. Die Subscriber verarbeiten die Nachricht unabhängig voneinander.
Themenbasierte vs. ereignisbasierte Varianten
Themenbasiert (Topic-based)
Subscriber abonnieren Nachrichten zu bestimmten Themen (Topics). Beispiel:
topic = "sensor/temperatur"
Alle Subscriber dieses Topics erhalten die Nachrichten.
Ereignisbasiert (Event-based)
Nachrichten definieren spezifische Ereignisse, z. B.:
Event: "Benutzer wurde erstellt"
Nur Subscriber dieses Ereignisses werden informiert.
Beispiel in Python (vereinfachter Event-Bus)
class EventBus:
def __init__(self):
self.subscribers = {}
def subscribe(self, event, callback):
self.subscribers.setdefault(event, []).append(callback)
def publish(self, event, data):
for callback in self.subscribers.get(event, []):
callback(data)
bus = EventBus()
def handler(msg):
print("Empfangen:", msg)
bus.subscribe("test_event", handler)
bus.publish("test_event", "Hallo Pub/Sub")
Beispiele in realen Systemen
| System | Rolle | RabbitMQ | Topic/Fanout Exchanges für Pub/Sub | Apache Kafka | Verteilt Nachrichtenströme an Consumer-Gruppen | Redis Pub/Sub | Leichtgewichtiges Pub/Sub-Modell in Infrastrukturanwendungen | WebSockets / Socket.IO | Ereignisbasierte Kommunikation in Echtzeit-Anwendungen | Cloud Pub/Sub (Google/AWS/Azure) | Globale Messaging-Systeme für verteilte Microservices |
|---|
Vorteile
- Lose Kopplung zwischen Komponenten
- Hohe Skalierbarkeit durch parallele Verarbeitung
- Unterstützt verteilte und eventgesteuerte Architekturen
- Wiederverwendbarkeit und Erweiterbarkeit der Systemkomponenten
Nachteile
- Nachrichtenfluss nicht direkt nachvollziehbar (Debugging komplexer)
- Keine garantierte Reihenfolge, wenn nicht explizit unterstützt
- Fehlerhandling und Retry-Strategien müssen bewusst implementiert werden
- Potenzielle Zustandsinkonsistenzen, wenn Ereignisse zeitlich variieren
Best Practices
- Nachrichten idempotent verarbeiten (Doppelausführung darf keine Fehler verursachen)
- Monitoring von Queues und Topics
- Verwendung eines zentralen Event-Schemas bei verteilten Teams
- Klare Namenskonventionen für Topics/Ereignisse
Vergleich zu anderen Mustern
| Muster | Vergleichspunkt | Unterschied |
|---|---|---|
| Pub/Sub | Kommunikation | Asynchron und entkoppelt |
| Observer | Kommunikation | Direkte Objektbeziehung ohne Broker |
| Competing Consumer | Verarbeitung | Mehrere Consumer teilen sich eine Queue (Lastverteilung), aber ohne Broadcast an mehrere Empfänger |
Zusammenfassung
Das Publisher-Subscriber-Entwurfsmuster ermöglicht asynchrone, lose gekoppelte Kommunikation zwischen Softwarekomponenten. Publisher senden Ereignisse ohne Wissen über Empfänger, während Subscriber flexibel Ereignisse abonnieren. Es bildet das Fundament vieler eventgesteuerter, verteilter und skalierbarer Softwaresysteme.
Siehe auch
- Competing-Consumer-Entwurfsmuster
- Mediator-Entwurfsmuster
- Event-Driven Architecture
- RabbitMQ
- Apache Kafka