STOMP (Simple Text Oriented Messaging Protocol) выступает как прикладной протокол поверх WebSocket, обеспечивающий структурированное взаимодействие между клиентом и сервером через брокер сообщений. В контексте JavaScript-библиотеки STOMP.js клиентская сторона реализует отправку и получение сообщений, а серверная часть чаще всего представлена брокером (RabbitMQ, ActiveMQ, Apache Artemis или Spring WebSocket Message Broker).
Ключевая архитектурная особенность заключается в разделении системы на три слоя:
WebSocket обеспечивает двунаправленный поток байтов, но не задаёт семантику сообщений. STOMP добавляет текстовые фреймы с командами, заголовками и телом, превращая поток в управляемый протокол взаимодействия.
STOMP реализует модель publish-subscribe и point-to-point через абстракции:
Клиент не работает напрямую с сетевыми адресами пользователей. Вместо этого он отправляет сообщения в логические маршруты, которые интерпретируются брокером.
Базовая схема выглядит следующим образом:
STOMP использует текстовые фреймы следующей структуры:
COMMAND
header1:value1
header2:value2
body^@
Каждое сообщение состоит из:
Ключевым моментом является то, что STOMP не навязывает формат тела: это может быть JSON, XML или произвольная строка.
STOMP.js является реализацией клиента STOMP поверх WebSocket API браузера. Он не реализует транспорт и не является брокером. Его функции ограничены:
Таким образом, STOMP.js — это протокольный адаптер между приложением и транспортом.
Сначала создаётся низкоуровневое соединение:
ws://server:port/ws
На этом этапе никакой логики сообщений ещё нет.
После установления WebSocket клиент отправляет фрейм:
CONNECT
accept-version:1.2
heart-beat:10000,10000
Сервер отвечает:
CONNECTED
version:1.2
heart-beat:10000,10000
На этом этапе создаётся STOMP-сессия, привязанная к WebSocket соединению.
Клиент формирует подписку:
SUBSCRIBE
id:sub-0
destination:/topic/chat
Каждая подписка имеет уникальный id, который используется для управления ACK и отмены подписки.
Отправка выполняется через SEND:
SEND
destination:/app/message
{"text":"hello"}
Важно, что destination интерпретируется серверной логикой. Часто используется разделение:
/app — входящие команды на сервер/topic — broadcast от сервера/queue — индивидуальные сообщенияСервер отправляет клиенту:
MESSAGE
subscription:sub-0
message-id:001
destination:/topic/chat
{"text":"hello"}
STOMP.js преобразует это в callback подписки.
Серверная часть STOMP-архитектуры обычно включает брокер сообщений. Он выполняет:
Topic (pub/sub): Сообщение получают все подписчики канала.
Queue (point-to-point): Сообщение получает один из потребителей.
STOMP поддерживает механизм heartbeat для обнаружения разрывов соединения.
Формат:
heart-beat:client,server
Где:
STOMP.js автоматически:
STOMP.js можно рассматривать как конечный автомат состояний:
Каждое состояние определяет допустимые операции:
Каждая подписка в STOMP.js хранится как объект:
ACK режим определяет, когда сообщение считается подтверждённым:
В архитектуре клиент-сервер STOMP ACK играет ключевую роль в надёжности доставки.
Сценарий:
Если ACK не получен, сообщение может быть переотправлено.
STOMP чаще всего используется в связке с:
Маршруты STOMP можно представить как пространство имён:
/topic/public
/topic/user/{id}
/queue/tasks
/app/command
Каждый сегмент определяет поведение:
/topic — broadcast/queue — очередь/app — серверная обработка/user — персонализированная маршрутизацияОдин клиент STOMP.js может:
Архитектурно это реализуется через мультиплексирование одного WebSocket соединения.
Полный цикл сообщения:
STOMP не масштабирует транспорт, он масштабирует логику доставки через брокер.
Типовые стратегии:
Несмотря на универсальность, архитектура STOMP имеет особенности:
WebSocket обеспечивает:
STOMP добавляет:
Таким образом, STOMP можно рассматривать как прикладной слой над WebSocket, формирующий полноценную message-driven архитектуру.