Vue d’ensemble — à quoi cela sert
Les tableaux de bord d’InfraGuard se mettent à jour sans rechargement de page. Ce rafraîchissement automatique repose sur deux mécanismes.
| Mécanisme | Comment | Latence | Utilisé par |
|---|---|---|---|
| WebSocket Reverb | Serveur → navigateur, envoi instantané (piloté par événements) | millisecondes | les tâches en direct qui diffusent leur progression sous forme de ticks |
| Interrogation légère | Le navigateur fait un GET sur /…/live à intervalle régulier |
jusqu’à 30 s | la plupart des tableaux de bord (Santé, Serveurs, Trafic, Service, Sécurité, Alertes …) |
Une règle de conception résume tout :
Le direct est une amélioration posée par-dessus des données persistées. Chaque écran affiche d’abord les données enregistrées en base, et les mises à jour temps réel viennent s’ajouter par-dessus. Ainsi, même si Reverb (le serveur WebSocket) est arrêté, bloqué par un pare-feu ou en cours de redémarrage, l’écran ne casse jamais. Lorsque l’envoi n’est pas disponible, l’interrogation prend le relais (dégradation élégante).
En pratique, presque tous les écrans fonctionnent par interrogation. Le WebSocket Reverb est installé et câblé, et il alimente aujourd’hui exactement une fonctionnalité : l’émulation distante du diagnostic de sécurité (Émulation distante · Diagnostic de sécurité), où il diffuse les ticks de progression par hôte. Tous les autres écrans en direct se rafraîchissent par interrogation toutes les 30 secondes, complétée par un jeton de détection de changement économique, rev.
Quand l’utiliser
Il s’agit d’une référence conceptuelle. Ce n’est pas un écran doté d’une route en direct : elle s’adresse aux exploitants et aux ingénieurs qui souhaitent comprendre :
- comment les tableaux de bord restent à jour d’eux-mêmes
- ce qui se passe dans les environnements où les WebSockets ne peuvent pas se connecter (réseaux internes, proxys, contenu mixte)
- comment l’interrogation économise la batterie et la charge serveur (elle se met en pause lorsque l’onglet passe en arrière-plan)
Disposition
Architecture à deux chemins
[données persistées] server_status · infr_db_metric · blacklist_info · …
│
▼ (chargement initial : le serveur injecte du JSON data-* dans la vue)
[écran du navigateur] ← rendu instantané (complet sans le direct)
▲ ▲
│ (A) interrogation │ (B) envoi Reverb
│ GET /…/live (≤30s) │ événement WS 'tick'
│ redessine si rev↑ seult │ ShouldBroadcastNow
[contrôleur Laravel] [serveur Reverb]
- (A) Interrogation — le front-end appelle
/{screen}/livetoutes les 30 secondes viasetInterval. La réponse porte un jeton de changement économique,rev; les graphiques et les cartes ne sont re-rendus que lorsqu’il change. Lorsque l’onglet est en arrière-plan (document.hidden), l’appel est ignoré. - (B) Envoi Reverb — le serveur diffuse un événement immédiatement (
ShouldBroadcastNow— sans file d’attente), et les navigateurs abonnés le reçoivent via le WebSocket. Aujourd’hui, cela sert uniquement aux ticks de progression de l’émulation distante.
Topologie de Reverb
| Élément | Valeur | Source |
|---|---|---|
| Bibliothèques client | laravel-echo + pusher-js |
import dynamique (exclu du bundle principal) |
Les détails de connexion du WebSocket sont configurés à l’installation. L’exploitant se contente d’ouvrir l’écran — il n’y a rien à paramétrer.
Comment l’utiliser
Exploitants — rien à faire
Le direct est automatique. Laissez un écran ouvert et l’interrogation récupère les dernières valeurs toutes les 30 secondes ; si le WebSocket est actif, les écrans pilotés par événements se mettent à jour instantanément. Pour économiser l’énergie, l’interrogation se met en pause tant que l’onglet est en arrière-plan et reprend lorsque vous y revenez.
Activer le WebSocket Reverb (facultatif)
L’envoi par WebSocket est configuré à l’installation par votre interlocuteur de déploiement — ce n’est pas une bascule accessible à l’exploitant dans la console. Si vous avez besoin d’envois temps réel, contactez votre administrateur ou l’éditeur.
Un envoi WebSocket désactivé n’est pas une erreur. C’est un interrupteur d’arrêt volontaire — les écrans en direct continuent de fonctionner avec la seule interrogation.
Ce que fait réellement l’interrogation
// Motif représentatif (p. ex. service-overview)
poll_ms: 30000,
this._poll = setInterval(() => {
if (this.live && !document.hidden) this.poll_tick(); // ignoré quand l’onglet est en arrière-plan
}, this.poll_ms);
// poll_tick → GET /service/live → re-rendu uniquement lorsque le rev de la réponse a changé
Le rev côté serveur est le signal de changement le plus économique possible. Par exemple, l’écran des métriques serveur utilise le MAX(seq) de la table historique server_status comme rev : cette valeur n’augmente que lorsque le collecteur insère un nouvel instantané.
// App\Services\Metric\ServerMetricService::rev()
return (int) DB::connection('legacy')->table('server_status')->max('seq');
La seule tâche en direct qui utilise l’envoi Reverb — l’émulation distante
L’émulation distante du Diagnostic de sécurité diffuse un tick de progression chaque fois qu’un hôte se termine.
- Événement :
App\Events\InfrRemoteEmulateTick(ShouldBroadcastNow) - Canal : un canal public,
infr.emulate.{runId}—runIdest un jeton aléatoire impossible à deviner (une capacité). Étant public, il ne nécessite aucun câblage/broadcasting/authbasé sur la session. - Nom d’événement :
.tick· la charge utile est légère (résumé de l’hôte et compteurs de progression uniquement) - Repli : le front-end s’abonne et, en parallèle, exécute une interrogation de repli toutes les 2 secondes (
/asset/remote/emulate-status/{runId}), de sorte que la progression n’est jamais perdue, même si le WS est absent ou si un tick initial a été manqué.
Sources de données
| Fichier | Rôle |
|---|---|
resources/js/echo.js |
L’unique constructeur Echo de l’application (SOT) — import dynamique · contrôle de configuration → null · forceTLS à l’exécution |
app/Support/Realtime.php |
Filet de sécurité de la diffusion (sonde fsockopen de up() · absorbeur d’exceptions de fire()) |
routes/channels.php |
Callbacks d’autorisation de canal (actuellement seulement le App.Models.User.{id} par défaut) |
app/Events/InfrRemoteEmulateTick.php |
Le seul événement de diffusion réellement utilisé |
le contrôleur …/live de chaque écran + …Service::rev() |
charge utile en direct pour l’interrogation + jeton de changement |
Realtime — défense à deux couches (le WS peut mourir sans emporter le travail d’origine)
// (1) up() — sonde fsockopen de 150 ms (mémoïsée par requête). Le broadcastWhen() d’un événement s’appuie dessus,
// de sorte que, Reverb étant à l’arrêt, un événement ShouldBroadcastNow ne lève PAS d’exception en ligne sur un timeout de connexion.
public static function up(): bool // sonde à partir de la configuration (aucune valeur en dur)
// (2) fire() — protège l’appelant même lorsque Reverb est en service mais refuse (413, ou 5xx pendant un redémarrage).
// Les échecs sont remontés via report() vers Pulse Exceptions ; le travail d’origine (un résultat d’analyse enregistré) réussit malgré tout.
public static function fire(object $event): void
Le broadcastWhen() d’un événement renvoie Realtime::up() — si Reverb est arrêté, il ignore totalement l’envoi.
Accès
Autorisation des canaux
| Type de canal | Authentification |
|---|---|
Canal public (infr.emulate.{runId}) |
aucune — le jeton de capacité runId constitue lui-même le droit d’accès (impossible à deviner) |
| canaux private / presence (feuille de route de conception) | le callback de routes/channels.php vérifie le user_level de session + la portée du rôle |
Le tableau des canaux temps réel de CLAUDE.md (
private-infr.server.{id},private-infr.threats,presence-infr.ops, …) est une feuille de route de conception. La diffusion réellement implémentée aujourd’hui se limite à l’unique canal publicinfr.emulate.{runId}, etroutes/channels.phpn’enregistre que le canal privéApp.Models.User.{id}fourni par défaut par le framework. Lorsque des canaux private/presence seront ajoutés, autorisez toujours selon leuser_levelet la portée (p. ex.infr.threatsexigeuser_level>=2 && scope∋security).
Accès aux points de terminaison d’interrogation
Les points de terminaison d’interrogation /{screen}/live héritent du contrôle de niveau de lecture du contrôleur de leur écran (demo=1, staff=5, admin=10 ; certaines zones sont protégées par le middleware infr.level:N). Par exemple, l’interrogation de repli sur l’état de l’émulation distante (emulate-status) requiert un accès en écriture (niveau ≥2). Voir Niveaux RBAC pour la politique complète.
Dépannage et FAQ
Q. Les WebSockets ne se connectent pas, mais l’écran continue de se mettre à jour ?
C’est le comportement attendu. Les écrans en direct sont pleinement fonctionnels en interrogation sans WS. Les WebSockets ne font que réduire la latence des tâches pilotées par événements, comme l’émulation distante.
Q. J’ai activé Reverb mais le navigateur ne se connecte pas
- Contenu mixte —
echo.jsdétermineforceTLSd’après le protocole de la page à l’exécution (wsslorsque la page est enhttps:). Il évite délibérément de le forcer depuis une variable de build : cela empêche un bundle servi en https de tenterws://et d’être bloqué par le navigateur. Si le front-end est en https, Reverb doit lui aussi servir en TLS (wss) ou un proxy doit assurer la terminaison. - CSP / CORS —
echo.jsdéfinitenabledTransports: ['ws','wss']+disableStats: truepour bloquer le repli CDN sockjs de pusher-js ainsi que les appels de statistiques (qui violeraient une CSP en auto-hébergement).
Q. Le tableau de bord sollicite-t-il trop le serveur / la base ?
- L’intervalle d’interrogation est de 30 secondes, et il s’arrête lorsque l’onglet passe en arrière-plan (
document.hidden). - Le jeton de changement
rev(p. ex.MAX(seq)) évite les re-rendus coûteux en l’absence de nouvelles données. - Les services qui construisent les données en direct sont pour la plupart mis en cache pendant 20 à 30 secondes.
Q. Puis-je planifier les daemons temps réel ?
Jamais. Ne lancez pas depuis le planificateur (
Schedule::command(...)) des daemons à boucle infinie tels quereverb:start,queue:workoupulse:check. Les processus qui ne se terminent jamais s’empilent à chaque tick et épuisent le pool de connexions MySQL partagé (mesuré le 2026-08-06 avecpulse:check: 169 accumulés en 16 heures →[1040] Too many connections, avec un impact sur la base de production). N’exécutez les daemons que depuis l’unique volet persistant du lanceur (développement) ou via supervisor/systemd (production). Voir Développement · Observabilité pour l’emplacement des daemons.
Q. Comment redémarrer Reverb après une modification de code ?
En production, php artisan reverb:restart sans interruption de service (ou redémarrez-le sous supervisor). En développement, redémarrez le volet du lanceur. Si le WS refuse brièvement les connexions pendant le redémarrage, Realtime::fire() absorbe l’exception et l’interrogation comble le vide.
Voir aussi
- Émulation distante — la seule tâche en direct qui utilise réellement l’envoi Reverb
- Diagnostic de sécurité — l’écran où circulent les ticks de progression de l’émulation distante
- Développement · Observabilité (Pulse) — discipline d’exécution des daemons · où atterrissent les exceptions de Realtime
- Infrastructure ▸ Serveurs — l’exemple canonique d’interrogation à 30 s + jeton rev
MAX(seq) - Vue d’ensemble des services — le motif d’interrogation du tableau en direct
- Niveaux RBAC — contrôles d’accès pour les canaux et les points de terminaison d’interrogation
