Отправка сообщений в STOMP.js опирается на корректную работу нескольких уровней: WebSocket-соединения, STOMP-фрейма, брокера сообщений и клиентской реализации очередей. Ошибка на любом из этих уровней приводит к сбоям доставки, которые часто проявляются не сразу, а в виде отсутствия реакции сервера или разрыва соединения.
Наиболее частая причина ошибок отправки связана с состоянием WebSocket. STOMP.js использует WebSocket как транспорт, и любые сбои на этом уровне делают отправку невозможной.
Типичные сценарии:
sendCONNECTINGПри попытке отправки в таком состоянии библиотека либо выбрасывает ошибку, либо «молча» игнорирует вызов, в зависимости от реализации клиента.
Критически важно учитывать состояние клиента перед отправкой:
client.connected === trueonWebSocketCloseconnect handshakeИгнорирование этих условий приводит к потере сообщений без явного исключения.
STOMP-протокол строго регламентирует структуру отправляемого сообщения. Любое отклонение приводит к отказу брокера принять сообщение.
Классический фрейм отправки:
SEND
destination:/queue/test
content-type:application/json
{"data":123}
Ошибки возникают при:
destination/queue/
или /topic/)content-typeНекоторые брокеры (RabbitMQ, ActiveMQ, Artemis) реагируют по-разному: одни закрывают соединение, другие отправляют ERROR-фрейм.
STOMP.js не выполняет глубокую проверку данных. Любая передача payload уходит «как есть» после сериализации.
Проблемные случаи:
JSON.stringifyundefined или функций внутри payloadПример проблемной отправки:
client.publish({
destination: "/queue/test",
body: { message: "test" }
});
В зависимости от версии STOMP.js это может привести к:
"[object Object]"Корректный вариант:
client.publish({
destination: "/queue/test",
body: JSON.stringify({ message: "test" })
});
STOMP допускает передачу пользовательских заголовков, но брокеры часто накладывают ограничения.
Проблемные ситуации:
content-length, subscription)Некоторые брокеры автоматически вычисляют
content-length. Если клиент отправляет его вручную и
значение не совпадает с фактическим телом, сообщение может быть
отклонено или обрезано.
STOMP.js работает асинхронно, но не всегда учитывает backpressure на уровне брокера.
При высокой частоте вызовов send или
publish возникают:
Особенно часто это проявляется при циклической отправке:
setInterval(() => {
client.publish({
destination: "/queue/load",
body: JSON.stringify(largePayload)
});
}, 10);
Если брокер не успевает обрабатывать поток, соединение может быть принудительно закрыто.
destination является ключевым элементом маршрутизации
сообщения. Ошибки в его формировании приводят к тому, что сообщение
формально отправлено, но не доставлено ни одному подписчику.
Типичные ошибки:
/queue и /topicНапример:
destination: "queue/test" // некорректно
destination: "/queue//test" // некорректно
Брокер может принять сообщение, но оно будет потеряно в routing layer.
STOMP по умолчанию не гарантирует delivery acknowledgment на уровне отправки. Это приводит к ситуации, когда клиент считает сообщение отправленным, но сервер его не обработал.
Проблемы усиливаются при:
auto ack режимаДля диагностики необходимо использовать:
STOMP поддерживает транзакции, но STOMP.js реализует их ограниченно. Ошибки возникают при:
commit без beginПример некорректного сценария:
client.begin("tx1");
client.publish({
destination: "/queue/test",
body: "data",
transaction: "tx1"
});
client.commit("tx1");
Если commit не доходит до брокера, все сообщения
транзакции отбрасываются.
Брокер может вернуть STOMP ERROR frame, но STOMP.js не всегда обрабатывает его как исключение.
Причины появления ERROR:
Пример фрейма:
ERROR
message:malformed frame
content-type:text/plain
Invalid destination
Если клиент не подписан на обработку ошибок, они теряются, и разработчик не видит причины сбоя отправки.
При автоматическом переподключении возможна ситуация, когда отправка происходит в момент восстановления соединения.
Сценарий:
send до завершения
CONNECTОтсутствие очереди отправки приводит к нестабильному поведению при нестабильной сети.
Некоторые ошибки отправки связаны не с кодом, а с различиями реализации STOMP:
Например, брокер может требовать STOMP 1.2, а клиент отправляет 1.0, из-за чего отправка проходит частично или блокируется.
Heartbeat используется для поддержания соединения. При его неправильной настройке возможны побочные эффекты:
Если heartbeat интервал слишком агрессивный, соединение может закрываться прямо во время отправки кадра.
WebSocket имеет внутренний буфер отправки. При переполнении:
send может не бросить ошибкуSTOMP.js не всегда отслеживает состояние bufferedAmount, что приводит к «тихим» потерям сообщений при высокой нагрузке.
В реальных системах между клиентом и брокером часто присутствуют промежуточные компоненты:
Они могут:
Для STOMP.js такие сбои выглядят как обычный network failure.
Отправка в STOMP.js не гарантирует моментальную доставку. Ошибки возникают, когда логика приложения предполагает синхронный результат:
client.publish({...});
updateUI(); // предполагается, что сообщение уже доставлено
Фактически отправка может быть отложена WebSocket слоем, и при разрыве соединения сообщение не уйдёт вовсе.
Ошибки отправки в STOMP.js почти всегда являются результатом комбинации факторов: состояния соединения, структуры STOMP-фрейма, поведения брокера и сетевой нестабильности.