Überblick — was das leistet
Die Dashboards von InfraGuard aktualisieren sich ohne Neuladen der Seite. Diese automatische Aktualisierung läuft über zwei Mechanismen.
| Mechanismus | Wie | Latenz | Verwendet von |
|---|---|---|---|
| Reverb-WebSocket | Server → Browser, sofortiger Push (ereignisgesteuert) | Millisekunden | Live-Jobs, die ihren Fortschritt als Ticks streamen |
| Schlankes Polling | Der Browser sendet in Intervallen ein GET auf /…/live |
bis zu 30 s | die meisten Dashboards (Zustand, Server, Traffic, Service, Sicherheit, Alarme …) |
Eine Design-Regel fasst alles zusammen:
Live ist eine Erweiterung, die auf persistierten Daten aufsetzt. Jeder Bildschirm rendert zuerst die in der Datenbank gespeicherten Daten, und die Echtzeit-Updates setzen darauf auf. Selbst wenn Reverb (der WebSocket-Server) abgeschaltet ist, von einer Firewall blockiert wird oder gerade neu startet, geht der Bildschirm daher nie kaputt. Ist Push nicht verfügbar, springt das Polling ein (Graceful Degradation).
In der Praxis läuft nahezu jeder Bildschirm über Polling. Das Reverb-WebSocket ist installiert und verdrahtet, und es treibt heute genau eine Funktion an — die Fernemulation der Sicherheitsdiagnose (Fernemulation · Sicherheitsdiagnose), wo es Fortschritts-Ticks pro Host streamt. Alle übrigen Live-Bildschirme aktualisieren sich mit 30-Sekunden-Polling plus einem billigen rev-Änderungstoken.
Wann Sie das nutzen
Dies ist eine konzeptionelle Referenz. Es ist kein Bildschirm mit Live-Route — sie richtet sich an Betreiber und Entwickler, die verstehen möchten:
- wie Dashboards sich von selbst aktuell halten
- was in Umgebungen passiert, in denen WebSockets keine Verbindung aufbauen können (interne Netze, Proxys, Mixed Content)
- wie Polling Akku und Serverlast spart (es pausiert, sobald der Tab in den Hintergrund wechselt)
Aufbau
Zwei-Pfad-Architektur
[persistierte Daten] server_status · infr_db_metric · blacklist_info · …
│
▼ (erster Seitenaufruf: der Server injiziert data-*-JSON in die View)
[Browser-Bildschirm] ← rendert sofort (auch ohne Live vollständig)
▲ ▲
│ (A) Polling │ (B) Reverb-Push
│ GET /…/live (≤30s) │ WS-Ereignis 'tick'
│ neu zeichnen nur bei rev↑│ ShouldBroadcastNow
[Laravel-Controller] [Reverb-Server]
- (A) Polling — das Frontend ruft alle 30 Sekunden über
setInterval/{screen}/liveauf. Die Antwort trägt ein billiges Änderungstoken,rev; Diagramme und Karten werden nur dann neu gerendert, wenn es sich ändert. Befindet sich der Tab im Hintergrund (document.hidden), entfällt der Aufruf. - (B) Reverb-Push — der Server sendet ein Ereignis sofort (
ShouldBroadcastNow— ohne Queue), und abonnierte Browser empfangen es über das WebSocket. Heute wird das ausschließlich für Fortschritts-Ticks der Fernemulation genutzt.
Reverb-Topologie
| Element | Wert | Quelle |
|---|---|---|
| Client-Bibliotheken | laravel-echo + pusher-js |
dynamischer Import (aus dem Haupt-Bundle ausgenommen) |
Die Verbindungsdetails des WebSockets werden bei der Installation eingerichtet. Betreiber öffnen einfach den Bildschirm — es gibt nichts zu konfigurieren.
Verwendung
Betreiber — nichts zu tun
Live läuft automatisch. Lassen Sie einen Bildschirm offen, und das Polling holt alle 30 Sekunden die aktuellen Werte; ist das WebSocket aktiv, aktualisieren sich ereignisgesteuerte Bildschirme sofort. Um Strom zu sparen, pausiert das Polling, solange der Tab im Hintergrund ist, und nimmt die Arbeit wieder auf, sobald Sie zurückkehren.
Das Reverb-WebSocket einschalten (optional)
WebSocket-Push wird bei der Installation von Ihrem Deployment-Ansprechpartner konfiguriert — es ist kein Schalter für Betreiber in der Konsole. Wenn Sie Echtzeit-Push benötigen, wenden Sie sich an Ihren Administrator oder an den Hersteller.
Ein abgeschalteter WebSocket-Push ist kein Fehler. Es ist ein bewusster Aus-Schalter — Live-Bildschirme arbeiten allein mit Polling weiter.
Was das Polling tatsächlich tut
// Repräsentatives Muster (z. B. service-overview)
poll_ms: 30000,
this._poll = setInterval(() => {
if (this.live && !document.hidden) this.poll_tick(); // überspringen, wenn der Tab im Hintergrund ist
}, this.poll_ms);
// poll_tick → GET /service/live → nur neu rendern, wenn sich das rev der Antwort geändert hat
Das serverseitige rev ist das denkbar billigste Änderungssignal. Der Bildschirm mit den Server-Metriken verwendet zum Beispiel MAX(seq) aus der Alt-Tabelle server_status als sein rev — der Wert steigt nur, wenn der Collector einen neuen Snapshot einfügt.
// App\Services\Metric\ServerMetricService::rev()
return (int) DB::connection('legacy')->table('server_status')->max('seq');
Der eine Live-Job, der Reverb-Push nutzt — die Fernemulation
Die Fernemulation der Sicherheitsdiagnose sendet jedes Mal einen Fortschritts-Tick, wenn ein Host fertig ist.
- Ereignis:
App\Events\InfrRemoteEmulateTick(ShouldBroadcastNow) - Kanal: ein öffentlicher Kanal
infr.emulate.{runId}—runIdist ein nicht erratbares Zufallstoken (eine Capability). Da er öffentlich ist, benötigt er keine sitzungsbasierte/broadcasting/auth-Verdrahtung. - Ereignisname:
.tick· die Nutzlast ist schlank (nur Host-Zusammenfassung und Fortschrittszähler) - Fallback: Das Frontend abonniert den Kanal und führt gleichzeitig ein 2-Sekunden-Fallback-Polling aus (
/asset/remote/emulate-status/{runId}), sodass der Fortschritt nie verloren geht — auch dann nicht, wenn das WS fehlt oder ein früher Tick verpasst wurde.
Datenquellen
| Datei | Rolle |
|---|---|
resources/js/echo.js |
Der einzige Echo-Builder der Anwendung (SOT) — dynamischer Import · Konfigurationsprüfung → null · forceTLS zur Laufzeit |
app/Support/Realtime.php |
Sicherheitsnetz für das Broadcasting (fsockopen-Sonde von up() · Ausnahme-Absorber von fire()) |
routes/channels.php |
Callbacks zur Kanalautorisierung (derzeit nur das voreingestellte App.Models.User.{id}) |
app/Events/InfrRemoteEmulateTick.php |
Das eine Broadcast-Ereignis, das tatsächlich im Einsatz ist |
der …/live-Controller jedes Bildschirms + …Service::rev() |
Live-Nutzlast für das Polling + Änderungstoken |
Realtime — zweischichtige Absicherung (das WS darf sterben, ohne die eigentliche Arbeit mitzureißen)
// (1) up() — 150 ms fsockopen-Sonde (pro Request memoisiert). Das broadcastWhen() eines Ereignisses hängt daran,
// sodass ein ShouldBroadcastNow-Ereignis bei abgeschaltetem Reverb KEINE Inline-Ausnahme wegen Verbindungs-Timeout wirft.
public static function up(): bool // sondiert anhand der Konfiguration (nichts fest verdrahtet)
// (2) fire() — schützt den Aufrufer auch dann, wenn Reverb läuft, die Anfrage aber ablehnt (413 oder 5xx während eines Neustarts).
// Fehler werden per report() an Pulse Exceptions gemeldet; die eigentliche Arbeit (ein gespeichertes Scan-Ergebnis) gelingt weiterhin.
public static function fire(object $event): void
Das broadcastWhen() eines Ereignisses gibt Realtime::up() zurück — ist Reverb abgeschaltet, entfällt der Versand vollständig.
Zugriff
Kanalautorisierung
| Kanaltyp | Authentifizierung |
|---|---|
Öffentlicher Kanal (infr.emulate.{runId}) |
keine — das Capability-Token runId ist die Zugriffsberechtigung (nicht erratbar) |
| private-/presence-Kanäle (Design-Roadmap) | Der Callback in routes/channels.php prüft das user_level der Sitzung + den Rollen-Scope |
Die Tabelle der Echtzeit-Kanäle in CLAUDE.md (
private-infr.server.{id},private-infr.threats,presence-infr.ops, …) ist eine Design-Roadmap. Der heute implementierte Broadcast ist der einzelne öffentliche Kanalinfr.emulate.{runId}, undroutes/channels.phpregistriert lediglich den vom Framework voreingestellten privaten KanalApp.Models.User.{id}. Wenn private-/presence-Kanäle hinzukommen, autorisieren Sie stets überuser_levelund Scope (z. B. verlangtinfr.threatsuser_level>=2 && scope∋security).
Zugriff auf die Polling-Endpunkte
Die Polling-Endpunkte /{screen}/live erben die Lesestufen-Prüfung des Controllers ihres Bildschirms (demo=1, staff=5, admin=10; einige Bereiche werden durch die Middleware infr.level:N abgesichert). Das Status-Fallback-Polling der Fernemulation (emulate-status) verlangt zum Beispiel Schreibzugriff (Stufe ≥2). Die vollständige Richtlinie finden Sie unter RBAC-Stufen.
Fehlerbehebung und FAQ
F. WebSockets verbinden sich nicht, aber der Bildschirm aktualisiert sich weiter?
Das ist so vorgesehen. Live-Bildschirme sind auch allein mit Polling voll funktionsfähig, ganz ohne WS. WebSockets senken lediglich die Latenz ereignisgesteuerter Jobs wie der Fernemulation.
F. Ich habe Reverb aktiviert, aber der Browser verbindet sich nicht
- Mixed Content —
echo.jsleitetforceTLSaus dem Seitenprotokoll zur Laufzeit ab (wss, wenn die Seitehttps:ist). Es erzwingt den Wert bewusst nicht über eine Build-Umgebungsvariable — so wird verhindert, dass ein über https ausgeliefertes Bundlews://versucht und vom Browser blockiert wird. Läuft das Frontend über https, muss auch Reverb TLS (wss) ausliefern oder ein Proxy muss es terminieren. - CSP / CORS —
echo.jssetztenabledTransports: ['ws','wss']+disableStats: true, um den sockjs-CDN-Fallback von pusher-js und dessen Statistikaufrufe zu unterbinden (die eine selbst gehostete CSP verletzen würden).
F. Belastet das Dashboard Server und Datenbank stark?
- Das Polling-Intervall beträgt 30 Sekunden, und es stoppt, sobald der Tab in den Hintergrund wechselt (
document.hidden). - Das Änderungstoken
rev(z. B.MAX(seq)) überspringt aufwendige Neuberechnungen, wenn keine neuen Daten vorliegen. - Die Dienste, die die Live-Daten aufbauen, sind größtenteils 20–30 Sekunden lang gecacht.
F. Kann ich die Echtzeit-Daemons über den Scheduler starten?
Niemals. Starten Sie Endlosschleifen-Daemons wie
reverb:start,queue:workoderpulse:checknicht aus dem Scheduler (Schedule::command(...)). Prozesse, die nie enden, häufen sich mit jedem Tick an und erschöpfen den gemeinsamen MySQL-Verbindungspool (gemessen am 2026-08-06 mitpulse:check: 169 angesammelte Prozesse in 16 Stunden →[1040] Too many connections, mit Auswirkungen auf die Produktionsdatenbank). Führen Sie Daemons ausschließlich aus dem einen dauerhaften Launcher-Pane (Entwicklung) oder über supervisor/systemd (Produktion) aus. Zur Platzierung von Daemons siehe Entwicklung · Observability.
F. Wie starte ich Reverb nach einer Codeänderung neu?
In der Produktion mit php artisan reverb:restart ohne Ausfallzeit (oder starten Sie es unter supervisor neu). In der Entwicklung starten Sie das Launcher-Pane neu. Weist das WS während des Neustarts kurzzeitig Verbindungen ab, fängt Realtime::fire() die Ausnahme ab und das Polling überbrückt die Lücke.
Verwandte Themen
- Fernemulation — der eine Live-Job, der Reverb-Push tatsächlich nutzt
- Sicherheitsdiagnose — der Bildschirm, über den die Fortschritts-Ticks der Fernemulation laufen
- Entwicklung · Observability (Pulse) — Disziplin beim Daemon-Betrieb · wo Realtime-Ausnahmen landen
- Infrastruktur ▸ Server — das kanonische Beispiel für 30-s-Polling +
MAX(seq)-rev-Token - Service-Übersicht — das Polling-Muster des Live-Boards
- RBAC-Stufen — Zugriffsprüfungen für Kanäle und Polling-Endpunkte
