Зачем нужен STOMP в веб-разработке

Веб-приложения долгое время строились вокруг классической модели HTTP-запросов. Браузер отправляет запрос серверу, сервер возвращает ответ. Такая схема подходит для загрузки страниц, REST API и большинства CRUD-операций, однако плохо работает в системах, где требуется постоянный обмен сообщениями в реальном времени.

Проблемы начинают проявляться в следующих сценариях:

  • онлайн-чаты;
  • биржевые терминалы;
  • системы мониторинга;
  • многопользовательские игры;
  • live-уведомления;
  • совместное редактирование документов;
  • панели аналитики;
  • системы логирования;
  • IoT и телеметрия.

В подобных приложениях серверу необходимо самостоятельно отправлять данные клиенту сразу после появления событий. Постоянный опрос сервера через HTTP (polling) создает лишнюю нагрузку, задержки и неэффективное использование сети.

Для решения этой проблемы появились WebSocket-соединения.


Почему одного WebSocket недостаточно

WebSocket предоставляет постоянное двустороннее соединение между браузером и сервером. После установки соединения стороны могут обмениваться данными без повторных HTTP-запросов.

Простейший пример:

const socket = new WebSocket('ws://localhost:8080');

socket.onmess age = (event) => {
    console.log(event.data);
};

socket.send('Hello');

Несмотря на простоту, WebSocket работает только на уровне транспорта. Он умеет:

  • устанавливать соединение;
  • отправлять строки или бинарные данные;
  • получать сообщения.

Но WebSocket не определяет:

  • структуру сообщений;
  • маршрутизацию;
  • подписки;
  • очереди;
  • обработку ошибок;
  • подтверждение доставки;
  • модель взаимодействия pub/sub.

Каждый проект начинает самостоятельно придумывать собственный протокол поверх WebSocket. В результате возникают проблемы:

  • несовместимость клиентов;
  • сложная поддержка;
  • отсутствие стандартизации;
  • дублирование логики;
  • усложнение масштабирования.

Именно здесь появляется STOMP.


Что такое STOMP

STOMP (Simple Text Oriented Messaging Protocol) — текстовый протокол обмена сообщениями поверх TCP или WebSocket.

Главная задача STOMP — превратить низкоуровневое WebSocket-соединение в полноценную систему обмена сообщениями.

STOMP вводит:

  • команды;
  • заголовки;
  • маршруты;
  • подписки;
  • брокеры сообщений;
  • очереди;
  • топики;
  • подтверждения сообщений.

Пример STOMP-фрейма:

SEND
destination:/app/chat

Hello World

STOMP делает WebSocket похожим на полноценную messaging-систему.


Что такое STOMP.js

STOMP.js — JavaScript-библиотека для работы с протоколом STOMP в браузере и Node.js.

Библиотека берет на себя:

  • подключение к брокеру;
  • отправку STOMP-фреймов;
  • подписки;
  • reconnect;
  • heartbeat;
  • обработку ошибок;
  • взаимодействие с WebSocket.

Типичный пример подключения:

import { Client } from '@stomp/stompjs';

const client = new Client({
    brokerURL: 'ws://localhost:8080/ws'
});

client.onConn ect = () => {
    console.log('Connected');

    client.subscribe('/topic/messages', (message) => {
        console.log(message.body);
    });

    client.publish({
        destination: '/app/chat',
        body: 'Hello'
    });
};

client.activate();

Главная проблема, которую решает STOMP

Без STOMP взаимодействие между клиентом и сервером быстро превращается в хаотичный обмен JSON-строками.

Например:

socket.send(JSON.stringify({
    type: 'NEW_MESSAGE',
    room: 'general',
    text: 'Hello'
}));

Со временем появляется необходимость:

  • разделять типы событий;
  • маршрутизировать сообщения;
  • поддерживать подписки;
  • фильтровать каналы;
  • отправлять broadcast;
  • гарантировать доставку;
  • масштабировать приложение.

Команды и форматы начинают разрастаться.

STOMP стандартизирует этот процесс.

Вместо ручного анализа type используются:

  • /topic
  • /queue
  • /app
  • SUBSCRIBE
  • SEND
  • ACK
  • NACK

Архитектура становится предсказуемой.


Модель Publish/Subscribe

Одной из ключевых причин использования STOMP является модель pub/sub (publish-subscribe).

Суть модели:

  • один клиент публикует сообщение;
  • множество клиентов получают его автоматически.

Пример:

/topic/news

Все подписчики топика получают новые сообщения.

Подписка:

client.subscribe('/topic/news', callback);

Отправка:

client.publish({
    destination: '/app/news',
    body: 'Breaking News'
});

Такая модель идеально подходит для:

  • чатов;
  • уведомлений;
  • новостных лент;
  • live-данных;
  • коллективной работы.

Разделение ответственности

STOMP помогает разделить роли компонентов системы.

WebSocket

Отвечает только за транспорт.

STOMP

Отвечает за messaging-протокол.

Message Broker

Отвечает за маршрутизацию сообщений.


Message Broker и STOMP

STOMP почти всегда используется вместе с брокерами сообщений.

Популярные брокеры:

  • RabbitMQ
  • Apache ActiveMQ
  • Apache Artemis
  • Spring Framework
  • Redis

Брокер берет на себя:

  • очереди;
  • маршрутизацию;
  • fanout;
  • topic exchange;
  • доставку;
  • балансировку;
  • масштабирование.

STOMP.js выступает клиентом этой системы.


Почему STOMP особенно популярен со Spring

Связка STOMP + WebSocket + Spring стала практически стандартом для Java backend.

Причина в том, что Spring предоставляет готовую инфраструктуру:

@EnableWebSocketMessageBroker

Маршруты:

/app
/topic
/queue

Контроллеры:

@MessageMapping("/chat")

Отправка сообщений:

@SendTo("/topic/messages")

На клиенте STOMP.js подключается практически без дополнительной настройки.


Почему STOMP лучше собственного протокола

Предсказуемость

Все клиенты используют одинаковые команды:

  • CONNECT
  • SEND
  • SUBSCRIBE
  • DISCONNECT

Универсальность

Можно заменить backend без переписывания frontend.

Стандартизация

Новые разработчики быстрее понимают архитектуру.

Интеграция

STOMP поддерживается множеством брокеров.

Масштабируемость

Система легче переносится на distributed-инфраструктуру.


Основные возможности STOMP

Подписки

client.subscribe('/topic/orders', callback);

Отправка сообщений

client.publish({
    destination: '/app/order',
    body: JSON.stringify(order)
});

Заголовки

client.publish({
    destination: '/app/chat',
    headers: {
        priority: 'high'
    },
    body: 'Message'
});

Подтверждение доставки

client.subscribe('/queue/tasks', callback, {
    ack: 'client'
});

Heartbeat

Позволяет отслеживать разрыв соединения.

Автоматический reconnect

reconnectDelay: 5000

Почему STOMP удобен именно для frontend

Frontend-разработчику сложно работать с низкоуровневыми messaging-системами.

Например, AMQP значительно сложнее:

  • exchanges;
  • bindings;
  • routing keys;
  • channels;
  • acknowledgements;
  • consumer lifecycle.

STOMP предоставляет упрощенный интерфейс.

Вместо сложной конфигурации:

client.subscribe('/topic/chat', callback);

Это делает STOMP.js удобным для:

  • React;
  • Vue;
  • Angular;
  • Next.js;
  • Nuxt;
  • SPA;
  • dashboard-приложений.

Реальные задачи, где применяется STOMP.js

Онлайн-чат

Пользователь отправляет сообщение:

client.publish({
    destination: '/app/chat',
    body: JSON.stringify(message)
});

Все клиенты получают обновление:

client.subscribe('/topic/messages', callback);

Live-курсы валют

Сервер публикует изменения курса.

Клиенты получают данные мгновенно без обновления страницы.


Мониторинг серверов

STOMP часто используется в:

  • DevOps-панелях;
  • системах логирования;
  • observability dashboard;
  • monitoring systems.

Уведомления

Push-like уведомления внутри веб-приложения:

  • новые сообщения;
  • изменения статуса;
  • обновления заказов;
  • события безопасности.

Совместная работа

Например:

  • редакторы документов;
  • kanban-доски;
  • совместные таблицы.

Изменения синхронизируются между клиентами в реальном времени.


Почему STOMP важен при масштабировании

Когда приложение работает на одном сервере, WebSocket может выглядеть простым.

Но при росте системы появляются проблемы:

  • несколько backend-инстансов;
  • балансировщики;
  • distributed-события;
  • очереди;
  • event-driven architecture.

STOMP хорошо вписывается в event-driven подход.

Серверы начинают обмениваться событиями через брокер сообщений, а браузеры получают данные через STOMP.js.


Архитектура без STOMP

Browser
   |
WebSocket
   |
Custom Protocol
   |
Backend

Недостатки:

  • собственный формат сообщений;
  • сложная поддержка;
  • отсутствие стандарта;
  • проблемы масштабирования.

Архитектура со STOMP

Browser
   |
STOMP.js
   |
WebSocket
   |
Message Broker
   |
Backend Services

Преимущества:

  • стандартизированный обмен;
  • pub/sub;
  • маршрутизация;
  • очереди;
  • масштабирование;
  • отказоустойчивость.

Текстовый формат STOMP

Одной из особенностей STOMP является текстовый формат фреймов.

Пример:

SUBSCRIBE
id:sub-1
destination:/topic/chat

^@

Преимущества текстового формата:

  • легко дебажить;
  • удобно анализировать трафик;
  • просто тестировать;
  • понятная структура.

Это особенно полезно при разработке и интеграции.


Отличие STOMP от Socket.IO

Socket.IO — популярная альтернатива для realtime-связи.

Однако подходы отличаются.

Socket.IO

  • собственный протокол;
  • тесная привязка к Node.js;
  • fallback-механизмы;
  • event-based API.

STOMP

  • открытый протокол;
  • broker-oriented;
  • интеграция с enterprise messaging;
  • независимость от backend-языка.

STOMP чаще применяется в enterprise-системах.


Отличие STOMP от MQTT

MQTT ориентирован прежде всего на IoT.

Особенности MQTT:

  • бинарный протокол;
  • минимальный overhead;
  • работа на слабых устройствах.

STOMP лучше подходит для веб-приложений и enterprise-backend.


Когда STOMP использовать не стоит

STOMP может быть избыточным для:

  • простых SPA;
  • небольших pet-проектов;
  • редких realtime-событий;
  • локальных WebSocket-соединений без брокера.

Иногда достаточно обычного WebSocket API.


Почему STOMP остается востребованным

Несмотря на появление новых realtime-технологий, STOMP продолжает активно использоваться благодаря нескольким факторам:

  • простота;
  • совместимость;
  • зрелость экосистемы;
  • поддержка enterprise-инфраструктуры;
  • интеграция с брокерами;
  • стандартизированный протокол;
  • удобство для frontend и backend одновременно.

Для крупных систем STOMP остается одним из наиболее удобных способов организации realtime-взаимодействия между браузером, backend-сервисами и message broker-инфраструктурой.