Модель передачи данных
и точки измерения
STOMP.js работает поверх WebSocket и передаёт данные в виде текстовых
кадров STOMP-протокола. Каждый кадр включает команду, заголовки и тело
сообщения. При профилировании передачи данных важно учитывать, что
фактическая стоимость коммуникации складывается из нескольких
уровней:
- WebSocket-фреймирование на транспортном уровне
- STOMP-кадры (заголовки + тело сообщения)
- Сериализация полезной нагрузки (JSON, бинарные строки, base64)
- Повторные доставки при переподключении
- Подписочная модель (fan-out на брокере)
Ключевые точки измерения:
- задержка доставки сообщения (end-to-end latency)
- размер STOMP-фрейма
- пропускная способность (messages per second)
- накладные расходы на соединение (handshake + heart-beat)
- время обработки сообщений клиентом
Измерение задержек
доставки сообщений
Задержка передачи в STOMP-системе должна измеряться на нескольких
этапах:
- Время отправки сообщения клиентом
- Время попадания в брокер
- Время маршрутизации по топику или очереди
- Время доставки обратно клиенту
- Время обработки callback-ом
subscribe
Практически применяемая схема меток времени:
clientSendTime
brokerReceiveTime (если доступно)
brokerDispatchTime
clientReceiveTime
Разница между clientSendTime и
clientReceiveTime даёт end-to-end latency.
Особое внимание следует уделять jitter — разбросу задержек. Даже при
низком среднем значении латентности система может быть нестабильной при
пиковых нагрузках.
Анализ размера STOMP-фреймов
STOMP.js передаёт данные в текстовом виде, поэтому размер сообщения
напрямую влияет на производительность сети и парсинг.
Структура типичного кадра:
SEND
destination:/topic/chat
content-type:application/json
{"message":"hello"}
\0
Основные источники накладных расходов:
- повторяющиеся заголовки (
destination,
content-type)
- JSON-сериализация
- терминатор кадра (
\0)
- UTF-8 кодирование
При профилировании фиксируются:
- средний размер кадра
- максимальный размер (outliers)
- распределение по типам сообщений
- доля заголовков в общем объёме
Практика показывает, что при частых мелких сообщениях накладные
расходы заголовков могут превышать полезную нагрузку.
Пропускная
способность и нагрузочное поведение
Пропускная способность STOMP.js определяется узким местом между
клиентом, сетью и брокером.
Метрики throughput:
- messages/sec на клиенте
- messages/sec на брокере
- aggregate bandwidth (bytes/sec)
- количество активных подписок
Типичный профиль деградации:
- при низкой нагрузке рост линейный
- при достижении порога сети наблюдается резкий рост latency
- далее начинается очередь сообщений на брокере
Важно учитывать, что WebSocket сам по себе не ограничивает поток,
поэтому backpressure реализуется на уровне приложения или брокера.
Профилирование подписок и
fan-out
Модель подписок в STOMP основана на топиках. Один опубликованный кадр
может быть доставлен множеству клиентов.
Стоимость fan-out зависит от:
- количества подписчиков на destination
- сложности маршрутизации в брокере
- размера сообщения
- политики доставки (persistent / non-persistent)
Метрики:
- время доставки одного сообщения всем подписчикам
- деградация при увеличении числа подписок
- нагрузка на GC из-за копирования сообщений
При большом количестве подписчиков критично измерять не только
среднюю задержку, но и хвост распределения (p95, p99).
Heart-beat и его влияние на
трафик
STOMP.js поддерживает механизм heart-beat для контроля живости
соединения. Он состоит из периодических пустых кадров.
Профилируемые параметры:
- частота отправки heartbeat
- размер контрольных кадров
- влияние на общий трафик при idle-соединениях
При высокой частоте heartbeat создаётся постоянный фон трафика,
который может быть значим при тысячах соединений.
Сетевые узкие
места и влияние WebSocket слоя
Хотя STOMP работает на уровне протокола сообщений, транспорт
WebSocket оказывает существенное влияние:
- TLS-рукопожатие при установке соединения
- TCP slow start
- влияние потерь пакетов на ретрансляцию
- head-of-line blocking
При профилировании важно разделять:
- задержки транспортного уровня
- задержки брокера
- задержки обработки в браузере
Профилирование
сериализации и десериализации
Основная нагрузка на клиенте возникает при:
- JSON.parse входящих сообщений
- JSON.stringify исходящих сообщений
- обработке callback-ов подписки
Метрики:
- время парсинга одного сообщения
- CPU usage при высокой частоте сообщений
- влияние крупных payload на event loop
Оптимизационный эффект достигается при уменьшении глубины объектов и
отказе от избыточных структур данных.
Очереди сообщений
и поведение при перегрузке
При перегрузке системы формируются очереди:
- на стороне брокера (internal queue)
- на стороне клиента (message buffer)
- на уровне TCP стеков
Симптомы перегрузки:
- рост latency без увеличения throughput
- рост memory usage в браузере
- задержка обработки подписок
Профилирование требует фиксации:
- длины очереди сообщений
- времени жизни сообщения в очереди
- частоты дропов (если брокер применяет ограничение)
Инструменты наблюдения в
браузере
Для анализа STOMP.js на клиенте используются:
- Performance API (User Timing)
- Network tab в DevTools (WebSocket frames)
- Memory profiling (heap snapshots)
- Event loop lag measurement
Практический подход:
- логирование timestamp на каждом этапе обработки сообщения
- измерение времени между
onMessage и завершением
обработки callback
- анализ блокировок main thread
Корреляция нагрузки и
поведения системы
Ключевая задача профилирования — выявление зависимости между
нагрузкой и деградацией:
- линейное масштабирование до определённого порога
- экспоненциальный рост задержек после saturation point
- нестабильность при burst-трафике
Фиксируются зависимости:
- messages/sec → latency
- number of subscriptions → CPU usage
- payload size → throughput
Эффекты
накопления нагрузки при длительной работе
Долгоживущие соединения STOMP.js требуют анализа долговременных
эффектов:
- утечки памяти при некорректном unsubscribe
- рост числа активных handler-ов
- деградация GC при большом количестве объектов сообщений
Особенно заметно при:
- постоянных потоках телеметрии
- чат-системах с высокой активностью
- системах уведомлений в реальном времени
Профилирование повторных
подключений
При разрывах соединения STOMP.js выполняет reconnect, который
включает:
- повторный CONNECT frame
- восстановление подписок
- возможную ресинхронизацию состояния
Метрики:
- время восстановления соединения
- количество потерянных сообщений
- нагрузка при массовом reconnect (thundering herd effect)
Анализ распределения
задержек
Средние значения латентности недостаточны для анализа. Важны:
- p50 (медиана)
- p95 (основной пользовательский опыт)
- p99 (краевые случаи)
Длинный хвост распределения часто возникает из-за:
- GC пауз в браузере
- перегрузки брокера
- сетевых ретрансляций
Итоговая модель
наблюдаемого потока данных
Система передачи данных STOMP.js может быть представлена как
цепочка:
клиент → WebSocket → STOMP broker → routing → fan-out → WebSocket →
клиент → обработка callback
Каждый участок добавляет собственную задержку и накладные расходы,
которые при профилировании должны рассматриваться отдельно, с
последующей корреляцией между слоями.