В протоколе STOMP доставка сообщения не считается завершённой в момент его получения клиентом. Завершённость определяется подтверждением обработки, которое отправляется обратно брокеру. Отсутствие подтверждения или явное отклонение приводит к повторной доставке либо перенаправлению сообщения в очередь повторных попыток или «мертвых писем» (dead-letter queue), в зависимости от конфигурации брокера.
В STOMP.js управление подтверждениями реализовано через объект
сообщения и методы ack() и nack(), которые
соответствуют семантике протокола STOMP 1.1/1.2.
Поведение отклонения сообщений напрямую зависит от режима подписки,
задаваемого при subscribe.
В автоматическом режиме подтверждение отправляется брокеру сразу после доставки сообщения клиенту. Любая ошибка обработки на стороне клиента не влияет на брокер: сообщение считается успешно обработанным.
Особенности:
В режиме клиентского подтверждения ответственность за подтверждение ложится на код обработки.
Сообщение должно быть явно подтверждено:
message.ack();
Если подтверждение не отправлено, сообщение будет повторно доставлено при переподключении или истечении таймаута брокера.
Аналогичен CLIENT_ACK, но подтверждение относится строго к конкретному сообщению, а не к группе сообщений с одним subscription.
message.ack();
Поведение отклонения аналогично, но контроль более точечный и безопасный при параллельной обработке.
Отклонение сообщения выполняется через метод nack(),
который сообщает брокеру о невозможности обработки сообщения.
message.nack();
В зависимости от реализации брокера и заголовков подписки, отклонение может приводить к разным сценариям:
STOMP как протокол не фиксирует единое поведение после
nack, поэтому результат определяется серверной
реализацией.
При использовании STOMP-плагина RabbitMQ:
nack приводит к requeue по умолчанию;ActiveMQ может:
Повторная доставка является ключевым механизмом надёжности при отклонении.
При nack или отсутствии ack:
В STOMP.js повторная доставка часто сопровождается заголовком:
redelivered: trueчто позволяет отличить первичную доставку от повторной.
Отклонение сообщения обычно связано с ошибками бизнес-логики или инфраструктуры.
Типовые сценарии:
Сообщение содержит некорректную структуру или значения.
Реакция:
nack() без повторной обработки;Например, недоступность внешнего API.
Реакция:
nack() с ожиданием повторной доставки;Нестабильное состояние приложения или исключение.
Реакция:
nack() с последующим анализом логов;В STOMP поддерживаются транзакции, позволяющие группировать операции подтверждения.
const tx = client.begin();
message.ack({ transaction: tx.id });
tx.commit();
При отклонении:
const tx = client.begin();
message.nack({ transaction: tx.id });
tx.rollback();
Особенности транзакционного режима:
При работе с STOMP.js важны метаданные сообщения:
message-id — идентификатор сообщения;subscription — идентификатор подписки;ack — режим подтверждения;redelivered — признак повторной доставки.Эти поля используются брокером для отслеживания состояния доставки и принятия решения о повторной отправке.
В STOMP.js объект сообщения предоставляет интерфейс:
message.nack({
headers: {
// дополнительные параметры, если поддерживаются брокером
}
});
Возможные последствия:
Важно, что STOMP.js не реализует логику повторов самостоятельно — он только отправляет протокольную команду брокеру.
При многократных отклонениях сообщение может попадать в специальные очереди.
Используется для:
Финальная точка маршрута сообщений:
При использовании CLIENT_INDIVIDUAL или CLIENT_ACK в многопоточной обработке возникают типовые проблемы:
nack одного и того же сообщения;Корректная модель требует:
Сообщение зависает в состоянии unacked и повторяется после реконнекта.
AUTO_ACK исключает возможность отклонения, несмотря на вызов
nack().
Отсутствие обработки повторных доставок приводит к бесконечным циклам обработки.
Частое использование nack без анализа причины приводит к росту backlog.
Отклонение сообщений является частью модели at-least-once delivery:
nack увеличивает вероятность повторной доставки;В STOMP.js эта модель проявляется особенно явно, так как клиентская библиотека не хранит состояние доставки, а только передаёт команды брокеру.