Подключение клиента STOMP.js к брокеру сообщений является ключевым этапом организации двустороннего обмена данными в реальном времени. В основе модели лежит установление поверх WebSocket логического STOMP-соединения, через которое выполняется публикация сообщений, подписка на каналы и управление жизненным циклом сессии.
STOMP.js не реализует транспорт самостоятельно, а использует уже существующее WebSocket-соединение или его совместимые аналоги. Это означает, что первым шагом всегда создаётся транспортный слой, после чего поверх него инициализируется STOMP-клиент.
Типовая цепочка выглядит следующим образом:
WebSocket выступает лишь каналом передачи байтовых фреймов, тогда как STOMP определяет структуру сообщений, команды и семантику взаимодействия.
Современные версии STOMP.js используют фабричный подход через функцию
Stomp.over() или прямое создание клиента через
Client.
Пример инициализации:
import { Client } from '@stomp/stompjs';
const client = new Client({
brokerURL: 'ws://localhost:8080/ws',
reconnectDelay: 5000,
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000,
});
В данном случае:
brokerURL определяет WebSocket-адрес брокераreconnectDelay задаёт автоматическое переподключение
при разрыве соединенияheartbeatIncoming и heartbeatOutgoing
активируют механизм проверки живости соединенияАльтернативный вариант с явным WebSocket:
import { Client } from '@stomp/stompjs';
const socket = new WebSocket('ws://localhost:8080/ws');
const client = new Client({
webSocketFactory: () => socket,
});
Использование webSocketFactory особенно важно в случаях,
когда требуется полный контроль над транспортом: добавление заголовков,
прокси-логика, кастомные реализации WebSocket.
STOMP-клиент проходит несколько стадий жизненного цикла, каждая из которых определяет допустимые операции.
Основные состояния:
Переходы между состояниями управляются автоматически при
использовании client.activate() и
client.deactivate().
client.onConn ect = (frame) => {
console.log('Соединение установлено');
};
client.onStompEr ror = (frame) => {
console.error('Ошибка брокера:', frame.headers['message']);
};
client.activate();
Метод activate() инициирует подключение, после чего
клиент начинает выполнять STOMP-рукопожатие с сервером.
После установления WebSocket-соединения STOMP-клиент отправляет
команду CONNECT или STOMP (в зависимости от
версии протокола).
Формат включает заголовки:
accept-versionhostlogin и passcode (если требуется
аутентификация)Пример внутреннего представления:
CONNECT
accept-version:1.2
host:broker.example.com
login:user
passcode:password
\0
Брокер отвечает кадром CONNECTED, подтверждая успешную
инициализацию сессии:
CONNECTED
version:1.2
session:abc123
heart-beat:4000,4000
\0
С этого момента соединение считается установленным, и клиент может подписываться на каналы и отправлять сообщения.
Механизм heartbeat используется для контроля живости соединения и предотвращения “тихих” разрывов.
В STOMP.js параметры задаются в миллисекундах:
const client = new Client({
brokerURL: 'ws://localhost:8080/ws',
heartbeatIncoming: 5000,
heartbeatOutgoing: 5000,
});
Логика работы:
heartbeatOutgoing — клиент отправляет периодический
сигнал брокеруheartbeatIncoming — клиент ожидает сигнал от
брокераЕсли сигналы перестают поступать, соединение считается разорванным, и
при включённом reconnectDelay запускается процесс
переподключения.
После успешного выполнения CONNECT-рукопожатия вызывается обработчик
onConnect.
client.onConn ect = (frame) => {
const sessionId = frame.headers['session'];
};
Объект frame содержит:
Состояние подключения можно использовать как точку инициализации подписок и отправки сообщений.
Ошибки могут возникать на разных этапах:
Для обработки используется:
client.onStompEr ror = (frame) => {
const message = frame.headers['message'];
const details = frame.body;
};
Также важно учитывать низкоуровневые ошибки транспорта:
client.onWebSocketEr ror = (event) => {
console.error('WebSocket error');
};
STOMP.js поддерживает механизм восстановления соединения при разрывах.
const client = new Client({
brokerURL: 'ws://localhost:8080/ws',
reconnectDelay: 3000,
});
Алгоритм работы:
Важно учитывать, что подписки после переподключения не сохраняются
автоматически в некоторых конфигурациях и должны быть восстановлены
вручную через onConnect.
STOMP позволяет передавать произвольные заголовки при подключении:
const client = new Client({
brokerURL: 'ws://localhost:8080/ws',
connectHeaders: {
login: 'user',
passcode: 'secret',
deviceId: 'web-client-01'
}
});
Такая схема часто используется для:
Во многих серверных реализациях WebSocket может быть недоступен напрямую, поэтому используется SockJS как транспорт-обёртка.
import SockJS from 'sockjs-client';
import { Client } from '@stomp/stompjs';
const client = new Client({
webSocketFactory: () => new SockJS('http://localhost:8080/ws'),
});
SockJS автоматически выбирает доступный транспорт:
STOMP.js при этом остаётся неизменным на уровне протокола.
Корректное завершение соединения выполняется через
deactivate():
client.deactivate();
При вызове:
DISCONNECTЕсли требуется обработка завершения:
client.onDisconn ect = () => {
console.log('Соединение закрыто');
};
При нестабильных сетевых условиях STOMP.js может:
По этой причине архитектурно важно рассматривать STOMP как транспорт доставки “best effort”, а не гарантированную очередь сообщений.
В некоторых сценариях создаются отдельные STOMP-клиенты для разных доменов сообщений:
Каждый клиент имеет собственный WebSocket и независимый жизненный цикл, что упрощает изоляцию логики, но увеличивает нагрузку на сеть и сервер брокера.