Resumen — qué hace
Los paneles de InfraGuard se actualizan solos sin recargar la página. Esa actualización automática se apoya en dos mecanismos.
| Mecanismo | Cómo | Latencia | Lo usan |
|---|---|---|---|
| WebSocket de Reverb | Servidor → navegador, envío instantáneo (dirigido por eventos) | milisegundos | trabajos en vivo que transmiten el progreso como ticks |
| Sondeo ligero | El navegador hace GET a /…/live a intervalos |
hasta 30 s | casi todos los paneles (Estado, Servidores, Tráfico, Servicio, Seguridad, Alertas …) |
Una regla de diseño lo resume todo:
Lo «en vivo» es una mejora que se superpone a los datos persistidos. Cada pantalla renderiza primero los datos guardados en la base de datos, y las actualizaciones en tiempo real van encima. Por eso, aunque Reverb (el servidor WebSocket) esté apagado, bloqueado por un cortafuegos o reiniciándose, la pantalla nunca se rompe. Cuando el envío no está disponible, el sondeo cubre el hueco (degradación elegante).
En la práctica, casi todas las pantallas funcionan con sondeo. El WebSocket de Reverb está instalado y cableado, y hoy alimenta exactamente una función: la emulación remota del diagnóstico de seguridad (Emulación remota · Diagnóstico de seguridad), donde transmite ticks de progreso por host. Todas las demás pantallas en vivo se refrescan con un sondeo de 30 segundos más un token barato de detección de cambios, rev.
Cuándo usarlo
Esta es una referencia conceptual. No es una pantalla con ruta en vivo: está pensada para operadores e ingenieros que quieren entender:
- cómo se mantienen actualizados los paneles por sí solos
- qué ocurre en entornos donde los WebSockets no pueden conectarse (redes internas, proxies, contenido mixto)
- cómo el sondeo ahorra batería y carga del servidor (se pausa cuando la pestaña pasa a segundo plano)
Disposición
Arquitectura de dos caminos
[datos persistidos] server_status · infr_db_metric · blacklist_info · …
│
▼ (carga inicial de la página: el servidor inyecta JSON data-* en la vista)
[pantalla del navegador] ← se renderiza al instante (completa sin nada en vivo)
▲ ▲
│ (A) sondeo │ (B) envío de Reverb
│ GET /…/live (≤30s) │ evento WS 'tick'
│ repinta solo si rev↑ │ ShouldBroadcastNow
[controlador de Laravel] [servidor Reverb]
- (A) Sondeo — el front-end llama a
/{screen}/livecada 30 segundos mediantesetInterval. La respuesta lleva un token de cambio barato,rev; los gráficos y las tarjetas se vuelven a renderizar solo cuando cambia. Cuando la pestaña está en segundo plano (document.hidden), la llamada se omite. - (B) Envío de Reverb — el servidor difunde un evento de inmediato (
ShouldBroadcastNow, sin cola) y los navegadores suscritos lo reciben por el WebSocket. Hoy esto se usa únicamente para los ticks de progreso de la emulación remota.
Topología de Reverb
| Elemento | Valor | Origen |
|---|---|---|
| Bibliotecas de cliente | laravel-echo + pusher-js |
importación dinámica (excluidas del paquete principal) |
Los detalles de conexión del WebSocket se configuran durante la instalación. El operador solo tiene que abrir la pantalla: no hay nada que configurar.
Cómo usarlo
Operadores — nada que hacer
Lo «en vivo» es automático. Deje una pantalla abierta y el sondeo traerá los últimos valores cada 30 segundos; si el WebSocket está activo, las pantallas dirigidas por eventos se actualizan al instante. Para ahorrar energía, el sondeo se pausa mientras la pestaña está en segundo plano y se reanuda cuando vuelve a ella.
Activar el WebSocket de Reverb (opcional)
El envío por WebSocket lo configura su contacto de despliegue en el momento de la instalación: no es un interruptor para el operador dentro de la consola. Si necesita envío en tiempo real, contacte con su administrador o con el proveedor.
Que el envío por WebSocket esté apagado no es un error. Es un interruptor de apagado intencionado: las pantallas en vivo siguen funcionando solo con sondeo.
Qué hace realmente el sondeo
// Patrón representativo (p. ej. service-overview)
poll_ms: 30000,
this._poll = setInterval(() => {
if (this.live && !document.hidden) this.poll_tick(); // se omite si la pestaña está en segundo plano
}, this.poll_ms);
// poll_tick → GET /service/live → vuelve a renderizar solo cuando cambió el rev de la respuesta
El rev del lado del servidor es la señal de cambio más barata posible. Por ejemplo, la pantalla de métricas de servidor usa MAX(seq) de la tabla heredada server_status como su rev: el valor solo sube cuando el recolector inserta una instantánea nueva.
// App\Services\Metric\ServerMetricService::rev()
return (int) DB::connection('legacy')->table('server_status')->max('seq');
El único trabajo en vivo que usa el envío de Reverb: la emulación remota
La emulación remota de Diagnóstico de seguridad difunde un tick de progreso cada vez que termina un host.
- Evento:
App\Events\InfrRemoteEmulateTick(ShouldBroadcastNow) - Canal: un canal público,
infr.emulate.{runId};runIdes un token aleatorio imposible de adivinar (una capacidad). Al ser público, no necesita el cableado de/broadcasting/authbasado en sesión. - Nombre del evento:
.tick· la carga útil es ligera (solo el resumen del host y los contadores de progreso) - Respaldo: el front-end se suscribe y, al mismo tiempo, ejecuta un sondeo de respaldo de 2 segundos (
/asset/remote/emulate-status/{runId}), de modo que el progreso nunca se pierde aunque el WS no esté presente o se haya perdido un tick temprano.
Fuentes de datos
| Archivo | Papel |
|---|---|
resources/js/echo.js |
El único constructor de Echo de la aplicación (SOT) — importación dinámica · comprobación de configuración → null · forceTLS en tiempo de ejecución |
app/Support/Realtime.php |
Red de seguridad de la difusión (sonda fsockopen de up() · absorbedor de excepciones de fire()) |
routes/channels.php |
Callbacks de autorización de canales (por ahora solo el App.Models.User.{id} por defecto) |
app/Events/InfrRemoteEmulateTick.php |
El único evento de difusión realmente en uso |
el controlador …/live de cada pantalla + …Service::rev() |
carga útil en vivo para el sondeo + token de cambio |
Realtime — defensa en dos capas (el WS puede morir sin matar el trabajo original)
// (1) up() — sonda fsockopen de 150 ms (memorizada por petición). El broadcastWhen() de un evento se apoya en esto,
// de modo que, con Reverb caído, un evento ShouldBroadcastNow NO lanza una excepción en línea por timeout de conexión.
public static function up(): bool // sondea a partir de la configuración (sin valores fijos en el código)
// (2) fire() — protege a quien llama incluso cuando Reverb está en pie pero rechaza (413, o 5xx mientras se reinicia).
// Los fallos se envían con report() a Pulse Exceptions; el trabajo original (un resultado de análisis guardado) sigue teniendo éxito.
public static function fire(object $event): void
El broadcastWhen() de un evento devuelve Realtime::up(): si Reverb está apagado, omite el envío por completo.
Acceso
Autorización de canales
| Tipo de canal | Autorización |
|---|---|
Canal público (infr.emulate.{runId}) |
ninguna: el token de capacidad runId es la concesión de acceso (imposible de adivinar) |
| canales private / presence (hoja de ruta de diseño) | el callback de routes/channels.php comprueba el user_level de la sesión + el ámbito del rol |
La tabla de canales en tiempo real de CLAUDE.md (
private-infr.server.{id},private-infr.threats,presence-infr.ops, …) es una hoja de ruta de diseño. La difusión implementada hoy es el único canal públicoinfr.emulate.{runId}, yroutes/channels.phpsolo registra el canal privadoApp.Models.User.{id}que trae el framework por defecto. Cuando se añadan canales private/presence, autorice siempre poruser_levely ámbito (p. ej.infr.threatsexigeuser_level>=2 && scope∋security).
Acceso a los endpoints de sondeo
Los endpoints de sondeo /{screen}/live heredan el control de nivel de lectura del controlador de su pantalla (demo=1, staff=5, admin=10; algunas áreas están protegidas por el middleware infr.level:N). Por ejemplo, el sondeo de respaldo de estado de la emulación remota (emulate-status) exige acceso de escritura (nivel ≥2). Consulte Niveles RBAC para la política completa.
Solución de problemas y preguntas frecuentes
P. Los WebSockets no conectan, pero la pantalla se sigue actualizando
Es lo esperado. Las pantallas en vivo son plenamente funcionales con sondeo sin ningún WS. Los WebSockets solo reducen la latencia de trabajos dirigidos por eventos, como la emulación remota.
P. He activado Reverb pero el navegador no se engancha
- Contenido mixto —
echo.jsdecideforceTLSa partir del protocolo de la página en tiempo de ejecución (wsscuando la página eshttps:). Deliberadamente no lo fuerza desde una variable de compilación: así se evita que un paquete servido por https intentews://y el navegador lo bloquee. Si el front-end va por https, Reverb también debe servir TLS (wss) o un proxy debe terminarlo. - CSP / CORS —
echo.jsestableceenabledTransports: ['ws','wss']+disableStats: truepara bloquear el respaldo por CDN de sockjs de pusher-js y las llamadas de estadísticas (que violarían una CSP autoalojada).
P. ¿El panel machaca el servidor o la base de datos?
- El intervalo de sondeo es de 30 segundos y se detiene cuando la pestaña pasa a segundo plano (
document.hidden). - El token de cambio
rev(p. ej.MAX(seq)) evita renderizados costosos cuando no hay datos nuevos. - Los servicios que construyen los datos en vivo están cacheados, en su mayoría, entre 20 y 30 segundos.
P. ¿Puedo programar los daemons de tiempo real?
Nunca. No lance desde el planificador (
Schedule::command(...)) daemons de bucle infinito comoreverb:start,queue:workopulse:check. Los procesos que nunca terminan se acumulan en cada tick y agotan el pool compartido de conexiones de MySQL (medido el 2026-08-06 conpulse:check: 169 acumulados en 16 horas →[1040] Too many connections, afectando a la base de datos de producción). Ejecute los daemons únicamente desde el panel persistente único del lanzador (desarrollo) o con supervisor/systemd (producción). Consulte Desarrollo · Observabilidad para la ubicación de los daemons.
P. ¿Cómo reinicio Reverb tras un cambio de código?
En producción, php artisan reverb:restart sin corte de servicio (o reinícielo bajo supervisor). En desarrollo, reinicie el panel del lanzador. Si el WS rechaza conexiones brevemente durante el reinicio, Realtime::fire() absorbe la excepción y el sondeo cubre el hueco.
Relacionado
- Emulación remota — el único trabajo en vivo que realmente usa el envío de Reverb
- Diagnóstico de seguridad — la pantalla por la que fluyen los ticks de progreso de la emulación remota
- Desarrollo · Observabilidad (Pulse) — disciplina de ejecución de daemons · dónde aterrizan las excepciones de Realtime
- Infraestructura ▸ Servidores — el ejemplo canónico de sondeo de 30 s + token rev
MAX(seq) - Resumen de servicio — el patrón de sondeo del tablero en vivo
- Niveles RBAC — controles de acceso para canales y endpoints de sondeo
