InfraGuard

Живое обновление (Reverb + опрос)

Два способа, которыми экраны обновляются сами — мгновенные push-сообщения по WebSocket Reverb и лёгкий опрос раз в 30 секунд с дешёвым токеном изменений rev — и почему консоль никогда не ломается при выключенных WebSocket.

Обзор — что это даёт

Панели InfraGuard обновляются сами, без перезагрузки страницы. Это автообновление опирается на два механизма.

Механизм Как Задержка Кто использует
WebSocket Reverb Сервер → браузер, мгновенная отправка (событийная модель) миллисекунды живые задания, транслирующие прогресс в виде тиков
Лёгкий опрос Браузер с интервалом выполняет GET /…/live до 30 с большинство панелей (Состояние, Серверы, Трафик, Сервисы, Безопасность, Оповещения …)

Всё это сводится к одному принципу проектирования:

Живое обновление — это надстройка поверх сохранённых данных. Каждый экран сначала отрисовывает данные, сохранённые в БД, а обновления в реальном времени ложатся сверху. Поэтому даже если Reverb (сервер WebSocket) выключен, заблокирован межсетевым экраном или перезапускается, экран никогда не ломается. Когда push недоступен, его подменяет опрос (плавная деградация).

На практике почти каждый экран работает на опросе. WebSocket Reverb установлен и подключён, и сегодня он обслуживает ровно одну функцию — удалённую эмуляцию диагностики безопасности (Удалённая эмуляция · Диагностика безопасности), где транслирует тики прогресса по каждому хосту. Все остальные живые экраны обновляются 30-секундным опросом плюс дешёвым токеном обнаружения изменений rev.


Когда это применять

Это концептуальный справочник. Это не экран с живым маршрутом — материал предназначен для операторов и инженеров, которые хотят понять:


Устройство экрана

Архитектура из двух путей

[сохранённые данные]  server_status · infr_db_metric · blacklist_info · …
      │
      ▼ (первая загрузка страницы: сервер встраивает JSON data-* в представление)
[экран браузера]  ← отрисовывается мгновенно (полноценен и без живого обновления)
      ▲                          ▲
      │ (A) опрос                 │ (B) push от Reverb
      │  GET /…/live (≤30s)       │  событие WS 'tick'
      │  перерисовка только rev↑  │  ShouldBroadcastNow
   [контроллер Laravel]        [сервер Reverb]

Топология Reverb

Элемент Значение Источник
Клиентские библиотеки laravel-echo + pusher-js динамический импорт (исключены из основного бандла)

Параметры подключения WebSocket настраиваются при установке. Оператору достаточно открыть экран — настраивать нечего.


Как пользоваться

Операторам — делать ничего не нужно

Живое обновление работает автоматически. Оставьте экран открытым, и опрос будет забирать свежие значения каждые 30 секунд; если WebSocket включён, событийные экраны обновляются мгновенно. Ради экономии энергии опрос приостанавливается, пока вкладка находится в фоне, и возобновляется, когда вы к ней возвращаетесь.

Включение WebSocket Reverb (необязательно)

Push по WebSocket настраивает ваш ответственный за развёртывание во время установки — это не переключатель для оператора в консоли. Если вам нужен push в реальном времени, обратитесь к администратору или к поставщику.

Выключенный push по WebSocket — не ошибка. Это намеренный выключатель: живые экраны продолжают работать на одном лишь опросе.

Что на самом деле делает опрос

// Характерный шаблон (например, service-overview)
poll_ms: 30000,
this._poll = setInterval(() => {
    if (this.live && !document.hidden) this.poll_tick();   // пропустить, если вкладка в фоне
}, this.poll_ms);
// poll_tick → GET /service/live → перерисовка только при изменении rev в ответе

Серверный rev — это максимально дешёвый сигнал изменения. Например, экран серверных метрик использует в качестве rev значение MAX(seq) из устаревшей таблицы server_status: оно растёт только тогда, когда коллектор вставляет новый снимок.

// App\Services\Metric\ServerMetricService::rev()
return (int) DB::connection('legacy')->table('server_status')->max('seq');

Единственное живое задание, использующее push Reverb, — удалённая эмуляция

Удалённая эмуляция из раздела Диагностика безопасности рассылает тик прогресса каждый раз, когда очередной хост завершает работу.


Источники данных

Файл Роль
resources/js/echo.js Единственный сборщик Echo в приложении (SOT) — динамический импорт · проверка конфигурации → null · forceTLS во время выполнения
app/Support/Realtime.php Страховка для рассылки (проба fsockopen в up() · поглотитель исключений в fire())
routes/channels.php Колбэки авторизации каналов (сейчас только стандартный App.Models.User.{id})
app/Events/InfrRemoteEmulateTick.php Единственное реально используемое событие рассылки
контроллер …/live каждого экрана + …Service::rev() живая полезная нагрузка для опроса + токен изменений

Realtime — двухслойная защита (WS может умереть, не утянув за собой исходную работу)

// (1) up() — проба fsockopen с таймаутом 150 мс (мемоизируется на запрос). Метод broadcastWhen() события опирается на неё,
//     поэтому при недоступном Reverb событие ShouldBroadcastNow НЕ выбрасывает исключение по таймауту соединения прямо в коде.
public static function up(): bool  // пробует по конфигурации (без жёстко зашитых значений)

// (2) fire() — защищает вызывающий код даже тогда, когда Reverb работает, но отклоняет запрос (413 либо 5xx во время перезапуска).
//     Сбои отправляются через report() в Pulse Exceptions; исходная работа (сохранённый результат сканирования) всё равно завершается успешно.
public static function fire(object $event): void

Метод broadcastWhen() события возвращает Realtime::up() — если Reverb выключен, отправка пропускается полностью.


Права доступа

Авторизация каналов

Тип канала Аутентификация
Публичный канал (infr.emulate.{runId}) нет — токен-мандат runId сам по себе и есть разрешение на доступ (его невозможно угадать)
каналы private / presence (план развития) колбэк в routes/channels.php проверяет user_level сессии + область роли

Таблица каналов реального времени в CLAUDE.md (private-infr.server.{id}, private-infr.threats, presence-infr.ops, …) — это план развития. Реализованная сегодня рассылка представляет собой единственный публичный канал infr.emulate.{runId}, а routes/channels.php регистрирует лишь приватный канал App.Models.User.{id}, заданный фреймворком по умолчанию. Когда появятся каналы private/presence, всегда авторизуйте по user_level и области (например, infr.threats требует user_level>=2 && scope∋security).

Доступ к конечным точкам опроса

Конечные точки опроса /{screen}/live наследуют проверку уровня чтения контроллера своего экрана (demo=1, staff=5, admin=10; некоторые разделы закрыты посредником infr.level:N). Например, резервный опрос состояния удалённой эмуляции (emulate-status) требует доступа на запись (уровень ≥2). Полная политика описана в разделе Уровни RBAC.


Устранение неполадок и частые вопросы

В. WebSocket не подключается, но экран продолжает обновляться?

Так и задумано. Живые экраны полностью работоспособны на опросе и без WS. WebSocket лишь сокращает задержку для событийных заданий вроде удалённой эмуляции.

В. Я включил Reverb, но браузер не подключается

В. Не создаёт ли панель чрезмерную нагрузку на сервер и БД?

В. Можно ли запускать демоны реального времени через планировщик?

Ни в коем случае. Не запускайте из планировщика (Schedule::command(...)) демоны с бесконечным циклом, такие как reverb:start, queue:work или pulse:check. Процессы, которые никогда не завершаются, накапливаются на каждом тике и исчерпывают общий пул подключений MySQL (замерено 2026-08-06 на pulse:check: 169 накопленных процессов за 16 часов → [1040] Too many connections, с влиянием на промышленную БД). Запускайте демоны только из единственной постоянной панели лаунчера (разработка) либо через supervisor/systemd (продуктив). О размещении демонов см. Разработка · Наблюдаемость.

В. Как перезапустить Reverb после изменения кода?

В продуктиве — php artisan reverb:restart без простоя (либо перезапустите его под supervisor). В разработке перезапустите панель лаунчера. Если во время перезапуска WS ненадолго начнёт отклонять подключения, Realtime::fire() поглотит исключение, а опрос закроет паузу.


Смежные материалы

헤더의 LIVE 표시 — 화면이 스스로 갱신되는 중
헤더의 LIVE 표시 — 화면이 스스로 갱신되는 중