Skalierung & Hochverfügbarkeit
Eviworx ITSM ist für horizontale Skalierung ausgelegt. Worker-Services können über docker compose --scale auf mehrere Instanzen verteilt werden. Redis dient als zentrale Koordinationsschicht für Locks, Queues und PubSub.
Horizontale Skalierung mit Docker Compose
Worker-Services können mit dem --scale Flag auf mehrere Instanzen hochskaliert werden:
# Scale job-worker to 3 instances
docker compose up -d --scale job-worker=3
# Scale multiple services at once
docker compose up -d --scale job-worker=3 --scale email-worker=2 --scale report-generator=2
# Scale workflow-engine to 2 instances
docker compose up -d --scale workflow-engine=2
# Check status
docker compose ps
Hinweis: Bei Skalierung muss der container_name aus docker-compose.yaml entfernt werden, da Container-Namen eindeutig sein müssen. Docker vergibt dann automatisch eindeutige Namen.
Job-Worker Multi-Instance
Funktionsweise:
• Jede Instanz registriert sich mit einer eindeutigen INSTANCE_ID
• Distributed Locks via Redis verhindern, dass derselbe CronJob von mehreren Instanzen gleichzeitig ausgeführt wird
• Heartbeat alle 15 Sekunden (stale Instanzen werden erkannt)
• Das Feld executedBy hält fest, welche Instanz den Job ausgeführt hat
Lock-Mechanismus:
1. Instanz A versucht Lock zu erwerben: SET lock:cronjob:123 NX EX 300
2. Wenn erfolgreich → Job wird ausgeführt
3. Instanz B versucht denselben Lock → FAIL (already locked)
4. Nach Abschluss → Lock wird freigegeben
Konfiguration:
# docker-compose.yaml (remove container_name!)
job-worker:
# container_name: eviworx-job-worker ← REMOVE
environment:
- INSTANCE_ID= # Auto-generated per instance
Workflow-Engine Multi-Instance
Funktionsweise: • Step-Level Locks: Jeder Workflow-Step wird atomar gesperrt • Redis PubSub für Event-Verteilung (workflow:step:complete) • Circuit Breaker verhindert kaskadierende Ausfälle • Hängende Workflows (> 10 min) werden automatisch wieder aufgenommen Parallele Verarbeitung: • Instanz A verarbeitet Workflow 1, Step 3 • Instanz B verarbeitet Workflow 2, Step 1 • Instanz A verarbeitet Workflow 3, Step 5 → Keine Konflikte durch Step-Level Locking
Report-Generator Multi-Instance
Funktionsweise: • BullMQ verteilt Report-Jobs automatisch auf verfügbare Instanzen • Read-Only DB-Zugriff (helpdesk_readonly) - kein Schreibkonflikt möglich • Jede Instanz kann unabhängig Reports generieren • Ideal für hohe Report-Last (viele parallele CSV/PDF-Exporte) Skalierung: docker compose up -d --scale report-generator=3
Worker-Heartbeat-Monitoring
Heartbeat-System: • Jeder Worker sendet alle 15 Sekunden einen Heartbeat • Heartbeat enthält: Instance-ID, Timestamp, Status, Version • Stale Detection: Der Heartbeat-Eintrag verfällt nach 30 Sekunden; ohne neuen Heartbeat gilt die Instanz als offline Health-Endpoints: Job-Worker: http://localhost:3001/health/live Workflow-Engine: http://localhost:3003/health/live Report-Generator: http://localhost:3004/health/live Email-Worker: Port 3005 (HEALTH_PORT) Notification-Worker: Port 3006 (HEALTH_PORT) AV-Worker: Port 3007 (HEALTH_PORT)
Load Balancing via Traefik
Traefik als Reverse Proxy: • Automatische Service-Discovery via Docker Labels • TLS-Terminierung (SSL-Zertifikate) • HTTP → HTTPS Redirect • Health-Check-basiertes Routing (nur gesunde Instanzen erhalten Traffic) • security_opt: no-new-privileges:true Im Betrieb: • Kein manuelles Reload bei Konfigurations-Änderungen • Automatische Erkennung neuer Container-Instanzen • Built-in Health-Check-Integration • Dashboard für Monitoring (optional)
Backend: eine Instanz
Die lastintensiven Aufgaben – Jobs, Reports, E-Mail, Notifications und Workflows – laufen in Workern, die sich mehrfach starten lassen. Das Backend läuft auf einer Instanz und wird vertikal ausgestattet. Grund sind die Rate-Limiter: Sie zählen Requests im Arbeitsspeicher des Backend-Prozesses. Zwei Instanzen hinter dem Load Balancer hätten je einen eigenen Zähler. Das effektive Limit wäre damit doppelt so hoch wie konfiguriert, und ein Login-Schutz von „5 Fehlversuchen" würde faktisch 10 erlauben. Das Backend deshalb nicht mit --scale vervielfachen.
Wo der Zustand des Backends liegt:
| Bereich | Speicherort |
|---|---|
| Sessions, Berechtigungen, Caches | Redis, instanzübergreifend geteilt |
| Rate-Limiter (HTTP) | Arbeitsspeicher des Backend-Prozesses; ein Neustart setzt sie zurück |
| API-Key-Limits | Redis |
Für die allermeisten Installationen ist das kein Engpass: Die rechenintensiven Aufgaben liegen bei den Workern, das Backend bedient im Wesentlichen API-Requests.
Redis als Koordinationsschicht
Redis Funktionen für Skalierung: 1. Distributed Locks → CronJob-Execution (nur eine Instanz führt aus) → Workflow-Step-Locking (keine doppelte Verarbeitung) 2. BullMQ Queues → Email-Queue (fair distribution über Instanzen) → Notification-Queue → Report-Queue 3. PubSub → workflow:step:complete Events → Real-time Event-Verteilung an alle Instanzen 4. Cache → Session-Cache (instanzübergreifend geteilt) → Query-Cache, SLA-Calendar-Cache 5. Audit-Fallback → Bei DB-Ausfall werden Audit-Events in Redis gespeichert (7 Tage TTL) Wichtig: Redis ist passwort-geschützt. Alle REDIS_URL-Verbindungen verwenden das Format: redis://:PASSWORD@redis:6379
Ressourcenplanung
Development-Umgebung (Minimum)
| Ressource | Empfehlung |
|---|---|
| CPU | 4 Cores |
| RAM | 8 GB |
| Storage | 20 GB SSD |
| Instanzen | Alle Services je 1x |
Production-Umgebung (Empfohlen)
| Ressource | Empfehlung |
|---|---|
| CPU | 8+ Cores |
| RAM | 16-32 GB |
| Storage | 200+ GB SSD (je nach Upload-Volumen) |
| Job-Worker | 2-3 Instanzen |
| Email-Worker | 1-2 Instanzen |
| Workflow-Engine | 1-2 Instanzen |
| Report-Generator | 1-2 Instanzen |
| Notification-Worker | 1 Instanz |
Hochlast-Umgebung (Enterprise)
| Ressource | Empfehlung |
|---|---|
| CPU | 16+ Cores |
| RAM | 32-64 GB |
| Storage | 500+ GB NVMe SSD |
| Job-Worker | 3-5 Instanzen |
| Email-Worker | 2-3 Instanzen |
| Workflow-Engine | 2-3 Instanzen |
| Report-Generator | 2-4 Instanzen |
| PostgreSQL | Dedizierter Server empfohlen |
| Redis | Dedizierter Server empfohlen |
Skalierungs-Checkliste
- container_name aus docker-compose.yaml entfernen (für skalierte Services)
- REDIS_PASSWORD ist gesetzt und überall identisch
- Redis hat genügend Speicher für Queues und Locks
- PostgreSQL max_connections ist angepasst (Standard: 100)
- Health-Checks sind für alle Worker aktiviert
- Monitoring für Worker-Heartbeats eingerichtet
- Resource-Limits (memory/CPU) pro Service gesetzt
- Traefik konfiguriert für Load Balancing
Container-Konfiguration und Service-Details
Alle Konfigurationsvariablen im Detail