Warum wird mein ERP plötzlich zum Flaschenhals?
In Integrationsprojekten mit Apache Pulsar taucht früher oder später eine unbequeme Frage auf:
Warum reicht ein einzelnes externes System aus, um ein ansonsten stabiles ERP in die Knie zu zwingen?
Das Grundszenario ist meist simpel. Ein ERP-System konsumiert ein Topic, über das operative Transaktionen ausgelöst werden. Im Normalbetrieb stammen diese Nachrichten aus internen Workflows – kontrolliert, vorhersehbar, gut dimensioniert.
Probleme entstehen erst dann, wenn externe Systeme dasselbe Topic nutzen, etwa für:
- Korrekturbuchungen
- Massenimporte
- nachträgliche Datenbereinigungen
Das ERP selbst besitzt oft kein ausgeprägtes Rückstau- oder Priorisierungskonzept. Die Folge: Sobald externe Last ungebremst eintrifft, wird das System überfordert.
Warum ein ERP-Ticket das eigentliche Problem verfehlt
Der klassische Lösungsweg ist schnell skizziert:
- Ticket beim ERP-Hersteller eröffnen
- Lastszenario beschreiben
- auf Verbesserung hoffen
Selbst wenn das erfolgreich wäre, bleiben strukturelle Fragen unbeantwortet:
- Dürfen externe Systeme ungefiltert in interne Prozessketten eingreifen?
- Können wir interne und externe Nutzung überhaupt unterscheiden?
- Haben wir Steuerungs- und Beobachtungsmöglichkeiten?
Perspektivwechsel: Integration als Infrastrukturthema
Apache Pulsar ist mehr als ein Transportmechanismus. Durch Namespaces, ACLs und Pulsar Functions lässt sich Pulsar als aktive Datendrehscheibe einsetzen.
Die zentrale Idee dieses Artikels lautet:
Wenn Last problematisch ist, muss sie vor dem ERP kontrolliert werden – nicht im ERP.
Testaufbau: Das Problem reproduzierbar machen
Dieser Abschnitt beschreibt den vollständigen Testaufbau, so dass das Szenario 1:1 reproduzierbar ist. Es werden bewusst keine Annahmen über vorhandene Infrastruktur gemacht.
1. Pulsar lokal starten
Für die Erprobung wird ein einzelner lokaler Pulsar-Broker im Standalone-Modus verwendet. Damit sind Broker, BookKeeper und ZooKeeper in einem Prozess gebündelt.
podman run -it --rm \
-p 6650:6650 \
-p 8080:8080 \
docker.io/apachepulsar/pulsar:4.0.8 \
bin/pulsar standalone
- Port 6650: Pulsar Binary Protocol (Clients)
- Port 8080: Admin-API, Functions Worker
2. ERP-Namespace anlegen
Nach dem Start wechseln wir in die Pulsar-Shell:
pulsar-shell
Zunächst wird der Namespace für das ERP angelegt:
admin namespaces create public/erp
3. Definition des Topics
Im Test wird ein Topic verwendet:
- ERP-Eingangstopic (intern)
persistent://public/erp/command
Topics müssen in Pulsar nicht explizit angelegt werden – sie entstehen implizit beim ersten Zugriff.
4. Simulation des ERP-Consumers
Das ERP wird durch einen einfachen Pulsar-CLI-Consumer simuliert, der alle empfangenen Nachrichten auf STDOUT ausgibt.
export PULSAR_URL=pulsar://127.0.0.1:6650
pulsar-cli consumer \
-t persistent://public/erp/command \
-s erp
- Subscription-Name:
erp - Subscription-Typ: default (Shared)
Jede empfangene Nachricht wird sofort ausgegeben.
5. Interner Producer (Normalbetrieb)
Der interne Producer simuliert reguläre ERP-Workflows mit geringer, konstanter Last.
seq 1 10000000 | while read i; do
echo "erp-client-message-$i" \
| pulsar-cli producer \
-t persistent://public/erp/command
sleep 5
done
Eigenschaften:
- eine Nachricht alle 5 Sekunden
- konstante Last
- keine Burst-Phasen
Der Consumer empfängt entsprechend:
erp-client-message-1
erp-client-message-2
erp-client-message-3
6. Externer Producer (Störfall)
Der externe Producer simuliert ein Fremdsystem, das ungebremst Nachrichten erzeugt.
seq 1 10000000 | while read i; do
echo "external-client-message-$i" \
| pulsar-cli producer \
-t persistent://public/erp/command
done
Eigenschaften:
- keine Pausen
- maximale Sendegeschwindigkeit
- keinerlei Rücksicht auf den Consumer
Das Ergebnis am ERP-Consumer:
external-client-message-433
erp-client-message-9
external-client-message-434
external-client-message-435
external-client-message-436
external-client-message-437
Interne Nachrichten gehen im Strom externer Last nahezu unter.
Dispatch Rate als Kontrollversuch
Zum Vergleich wird ein Dispatch-Limit direkt auf dem ERP-Topic gesetzt:
admin topics set-dispatch-rate \
persistent://public/erp/command \
--dispatch-rate-period=1 \
--msg-dispatch-rate=1
Der Consumer erhält nun nur noch eine Nachricht pro Sekunde – unabhängig von der Quelle.
Anschließend wird das Limit wieder entfernt:
admin topics set-dispatch-rate \
persistent://public/erp/command \
--dispatch-rate-period=1 \
--msg-dispatch-rate=-1
Architekturentscheidung: Trennung der Eingangskanäle
Grundidee: Externe Producer werden durch Pulsar kontrolliert, nicht durch das ERP
Externe Systeme publizieren ihre Nachrichten in ein eigenes Pulsar-Topic
(persistent://public/external/command) und nicht direkt in das ERP-Topic.
Dieses Topic wird ausschließlich von einer Pulsar Function konsumiert,
die als einziger autorisierter Producer in das interne ERP-Topic schreibt.
Rate Limiting wird auf dem Dispatch der Function angewendet
und begrenzt damit exakt die Nachrichtenrate,
mit der externe Events das ERP erreichen.
Ein dedizierter Namespace für das externe System
Wir führen einen zweiten Namespace ein:
admin namespaces create public/external
Damit entstehen zwei explizite Kanäle:
| Herkunft | Topic |
|---|---|
| Intern | persistent://public/erp/command |
| Extern | persistent://public/external/command |
command.
Die Unterscheidung erfolgt ausschließlich über den Namespace.
So bleibt die semantische Bedeutung identisch,
während die Governance-Struktur explizit wird.
Routing mit einer Pulsar Function
Externe Nachrichten sollen weiterhin ins ERP gelangen – aber kontrolliert. Dazu nutzen wir eine Pass-Through-Pulsar-Function, die Nachrichten unverändert weiterleitet.
public final class Copy implements Function<byte[], byte[]> {
@Override
public byte[] process(byte[] input, Context context) {
if (input == null || input.length == 0) {
return null;
}
return input;
}
}
Deployment:
admin functions create \
--tenant public \
--namespace external \
--name route.copy \
--jar /abs/path/route-copy.jar \
--classname net.d2ux.stream.generic.route.Copy \
--inputs persistent://public/external/command \
--output persistent://public/erp/command
Der vollständige Quellcode der in diesem Artikel verwendeten und weiterer beispielhafter Pulsar Functions ist befinden sich in folgendem Repository:
https://forge.ext.d2ux.net/OpenLab/pulsar-stream-functions
Die Beispiele sind minimal gehalten und zeigen typische Einsatzmuster wie Routing, Filtering und kontrollierte Weiterleitung von Nachrichten.
Rate Limiting dort, wo es sinnvoll ist
Jetzt setzen wir das Limit ausschließlich auf dem externen Topic:
admin topics set-dispatch-rate \
persistent://public/external/command \
--dispatch-rate-period=5 \
--msg-dispatch-rate=1
Ergebnis:
- interne Nachrichten laufen ungebremst
- externe Last wird dosiert
- das ERP bleibt stabil
external-client-message-433
erp-client-message-9
external-client-message-434
erp-client-message-10
external-client-message-435
erp-client-message-11
external-client-message-436
erp-client-message-12
external-client-message-437
Zusätzlicher Nutzen: Beobachtbarkeit
Pulsar Functions liefern Metriken:
pulsar_function_received_total{tenant="public",namespace="external",name="route.copy"} 2919
Fazit
Der gezeigte Ansatz verdeutlicht, welchen Mehrwert ein architektonischer Perspektivwechsel bieten kann. Statt Überlastsituationen ausschließlich auf Applikationsebene zu adressieren, wird die Integrationsschicht selbst zum Ort der Steuerung.
Apache Pulsar ermöglicht es, Datenströme, Lastverhalten und Zugriffswege explizit zu strukturieren.
Durch die Trennung interner und externer Kanäle sowie gezieltes Rate Limiting lassen sich externe Einflüsse kontrollieren, ohne bestehende Kernsysteme zu verändern.
Der Fokus dieses Artikels lag bewusst auf dem Last- und Laufzeitverhalten der beschriebenen Architektur. In produktiven Umgebungen müssen die dargestellten Mechanismen jedoch durch geeignete Sicherheitsmaßnahmen ergänzt werden. Insbesondere gehören dazu klar definierte ACLs auf Namespace-Ebene, um verbindlich festzulegen, welche Systeme Topics publizieren oder konsumieren dürfen.
Erst das Zusammenspiel aus Struktur, Governance und Security macht aus einer technischen Lösung eine tragfähige Integrationsarchitektur.
Oft ist sie ein Hinweis auf fehlende Steuerung in der Architektur.
Bildnachweis: Das Pulsar-Logo ist eine eingetragene Marke der Apache Software Foundation. Verwendung im Rahmen redaktioneller Berichterstattung gemäß den offiziellen Richtlinien.