Подключение STOMP-клиента к брокеру поверх WebSocket проходит через несколько уровней: установление WebSocket-соединения, STOMP handshake (CONNECT frame), согласование протокола и подтверждение сессии. Сбой может возникнуть на любом этапе, и диагностика зависит от того, на каком уровне произошла ошибка.
Ошибки подключения условно делятся на несколько категорий: транспортные (WebSocket), протокольные (STOMP), серверные (broker-side), а также ошибки жизненного цикла соединения (таймауты, heartbeat, разрывы сети).
WebSocket — базовый транспорт для STOMP.js. Если соединение не установлено, STOMP даже не переходит к отправке CONNECT frame.
На уровне STOMP.js WebSocket ошибки проявляются через события:
onWebSocketErroronWebSocketCloseПример обработки:
import { Client } from "@stomp/stompjs";
const client = new Client({
brokerURL: "ws://localhost:15674/ws",
debug: (msg) => console.log(msg),
onWebSocketError: (event) => {
console.error("WebSocket error", event);
},
onWebSocketClose: (event) => {
console.warn("WebSocket closed", event.code, event.reason);
},
});
client.activate();
1000 — нормальное закрытие1006 — аварийное завершение (часто сеть)1011 — серверная ошибка1015 — TLS handshake failureКод 1006 наиболее проблемный, так как не содержит
причины на уровне протокола.
После установления WebSocket STOMP отправляет frame:
CONNECT
accept-version:1.2
host:broker
\0
Если сервер отклоняет соединение, подключение не завершается.
hostSTOMP.js предоставляет callback:
onStompErrorПример:
const client = new Client({
brokerURL: "ws://localhost:15674/ws",
connectHeaders: {
login: "user",
passcode: "password",
},
onStompError: (frame) => {
console.error("Broker error:", frame.headers["message"]);
console.error("Details:", frame.body);
},
});
Сервер может вернуть:
ERROR
message:Authentication failed
content-type:text/plain
Access denied
Ошибка содержит:
Наиболее частый сценарий при использовании брокеров (RabbitMQ, ActiveMQ, Apollo):
При ошибке аутентификации:
STOMP поддерживает heartbeat механизм:
heart-beat:10000,10000
Первое число — интервал отправки клиента, второе — сервера.
const client = new Client({
brokerURL: "ws://localhost:15674/ws",
heartbeatIncoming: 10000,
heartbeatOutgoing: 10000,
});
При нарушении heartbeat STOMP.js инициирует reconnection (если включено).
Подключение может зависнуть на этапе CONNECT.
Без дополнительных настроек соединение может оставаться в состоянии
CONNECTING.
const client = new Client({
brokerURL: "ws://localhost:15674/ws",
reconnectDelay: 5000,
});
В браузере WebSocket handshake подчиняется CORS-подобным ограничениям.
onWebSocketError вызываетсяБрокер может принудительно закрыть соединение:
onWebSocketCloseОсновные callbacks клиента:
onWebSocketErroronWebSocketCloseonStompErroronDisconnectonConnectconst client = new Client({
brokerURL: "ws://localhost:15674/ws",
reconnectDelay: 3000,
onConnect: () => {
console.log("Connected");
},
onStompError: (frame) => {
console.error("STOMP error", frame.body);
},
onWebSocketError: (event) => {
console.error("WS error", event);
},
onWebSocketClose: (event) => {
console.warn("WS closed", event.code);
},
});
Автоматическое переподключение является ключевым механизмом устойчивости.
При нестабильной сети фиксированный reconnectDelay неэффективен.
Реализуется стратегия увеличения задержки:
let delay = 1000;
function getNextDelay() {
delay = Math.min(delay * 2, 30000);
return delay;
}
Использование в STOMP.js:
const client = new Client({
brokerURL: "ws://localhost:15674/ws",
reconnectDelay: 0,
onWebSocketClose: () => {
setTimeout(() => {
client.activate();
}, getNextDelay());
},
});
Некорректные настройки сервера часто проявляются как “необъяснимые” ошибки подключения.
STOMP.js предоставляет механизм трассировки:
const client = new Client({
brokerURL: "ws://localhost:15674/ws",
debug: (str) => {
console.log(new Date().toISOString(), str);
},
});
WebSocket error → close 1006 → reconnect loop
WebSocket open → CONNECT → ERROR frame → disconnect
CONNECTED → idle → no heartbeat → close 1006
CONNECT → delay → no response → timeout → reconnect
Устойчивое подключение требует разделения логики:
При разрыве соединения требуется: