Автоматическое квитирование

Автоматическое квитирование (auto ack) в STOMP.js определяет режим, при котором сообщение считается успешно обработанным сразу после его доставки клиенту, без явного подтверждения со стороны приложения. Такой подход исключает необходимость вызова методов подтверждения и полностью перекладывает ответственность за фиксацию доставки на клиентскую библиотеку и брокер сообщений.

В протоколе STOMP квитирование является механизмом управления надёжностью доставки сообщений. Оно определяет момент, когда брокер может удалить сообщение из очереди или считать его успешно обработанным. В STOMP.js этот механизм реализуется через параметр ack при подписке на destination.

Автоматический режим квитирования задаётся значением ack: 'auto' при подписке. В этом случае каждое доставленное сообщение считается подтверждённым немедленно после передачи его в обработчик подписки.

client.subscribe('/queue/orders', (message) => {
  console.log(message.body);
}, { ack: 'auto' });

Внутренне STOMP.js не ожидает вызова message.ack() и не сохраняет состояние неподтверждённых сообщений для данной подписки. Как только кадр MESSAGE доставлен в callback, брокер получает неявное подтверждение на уровне протокола.

Поведение брокера при auto ack

При использовании автоматического квитирования брокер работает в модели доставки «at most once». Это означает, что сообщение:

  • доставляется клиенту не более одного раза;
  • не требует явного подтверждения;
  • может быть потеряно при сбое клиента после получения, но до обработки.

Фактически подтверждение фиксируется в момент передачи сообщения по WebSocket-соединению, а не после выполнения логики обработчика.

Отличия от ручного квитирования

Для понимания автоматического режима важно сопоставить его с альтернативными стратегиями.

client ack

client.subscribe('/queue/orders', (message) => {
  process(message.body);
  message.ack();
}, { ack: 'client' });

В этом режиме подтверждение отправляется только после явного вызова ack(). Сообщение остаётся неподтверждённым до завершения обработки.

client-individual ack

client.subscribe('/queue/orders', (message) => {
  process(message.body);
  message.ack();
}, { ack: 'client-individual' });

Каждое сообщение подтверждается отдельно, даже если брокер поддерживает групповые подтверждения.

Особенности реализации auto ack в STOMP.js

STOMP.js реализует автоматическое квитирование на уровне клиента, а не брокера. Это означает, что:

  • заголовок ack в SUBSCRIBE кадре устанавливается в значение auto;
  • объект сообщения не содержит необходимости вызывать ack() или nack();
  • любые попытки вызова подтверждения игнорируются или не приводят к дополнительным STOMP-командам.

Пример SUBSCRIBE кадра:

SUBSCRIBE
id:sub-0
destination:/queue/orders
ack:auto

^@

Гарантии доставки

Автоматическое квитирование напрямую влияет на семантику доставки сообщений. Основная характеристика режима — отсутствие гарантии обработки после получения.

Сценарий потери сообщения возможен в следующих случаях:

  • разрыв WebSocket-соединения после получения сообщения;
  • исключение в обработчике до завершения логики;
  • аварийное завершение клиента.

В таких условиях брокер уже считает сообщение подтверждённым и не предпринимает повторной доставки.

Обработка ошибок в auto ack режиме

Так как подтверждение происходит автоматически, ошибки обработки не влияют на жизненный цикл сообщения. Это создаёт необходимость вынесения критически важной логики в дополнительные механизмы:

  • идемпотентность обработчиков;
  • внешние журналы обработки;
  • повторная публикация сообщений на уровне приложения;
  • использование компенсирующих очередей.
client.subscribe('/queue/orders', async (message) => {
  try {
    await processOrder(JSON.parse(message.body));
  } catch (e) {
    logError(e, message.body);
  }
}, { ack: 'auto' });

Даже при ошибке сообщение уже считается подтверждённым, поэтому повторной доставки не произойдёт.

Влияние на производительность

Автоматическое квитирование минимизирует накладные расходы:

  • отсутствуют дополнительные STOMP-команды ACK;
  • уменьшается количество сетевых кадров;
  • снижается нагрузка на брокер по учёту неподтверждённых сообщений.

В системах с высокой пропускной способностью это может существенно улучшить throughput, особенно при большом количестве коротких сообщений.

Типовые сценарии использования

Auto ack применяется в ситуациях, где потеря отдельного сообщения допустима или компенсируется другими механизмами:

  • телеметрия и метрики;
  • логирование событий;
  • потоковые данные без критичности;
  • UI-обновления состояния;
  • системы, где важна скорость доставки, а не гарантированная обработка.

В противоположность этому, финансовые операции, заказы и транзакционные события требуют более строгих режимов квитирования.

Взаимодействие с транзакциями

Автоматическое квитирование не связано с STOMP-транзакциями. Даже при использовании транзакционного контекста подтверждение доставки сообщения не откладывается.

Это означает, что:

  • auto ack игнорирует транзакционную границу;
  • сообщение подтверждается до участия в любой клиентской транзакции;
  • rollback транзакции не влияет на факт получения сообщения.

Ограничения модели

Основные ограничения автоматического квитирования:

  • невозможность повторной доставки после сбоя клиента;
  • отсутствие контроля над моментом подтверждения;
  • потеря семантики «at least once»;
  • зависимость надёжности от стабильности соединения.

Эти ограничения делают режим подходящим только для потоков данных, где допустима деградация точности ради скорости обработки.

Сравнение семантик доставки

Автоматическое квитирование формирует модель «at most once», тогда как альтернативные режимы дают другие гарантии:

  • auto: максимум одна доставка, возможна потеря;
  • client: минимум одна обработка при корректной логике повторов;
  • client-individual: более точный контроль подтверждений на уровне сообщений.

Выбор режима напрямую влияет на архитектуру всей системы обработки сообщений, включая устойчивость к сбоям и стратегию повторной обработки.