Версии протокола

STOMP-протокол развивался как текстовый протокол поверх WebSocket и TCP, и его версии отражают эволюцию требований к обмену сообщениями, совместимости и управлению соединением. В STOMP.js выбор версии протокола напрямую влияет на формат заголовков, правила экранирования, поддержку heartbeat-механизма и поведение подтверждений сообщений.

Первая официальная версия протокола задавала минимально необходимый набор возможностей для обмена сообщениями между клиентом и брокером.

Базовая модель кадра

STOMP 1.0 использует текстовый фрейм следующей структуры:

  • команда (COMMAND)
  • заголовки (headers)
  • пустая строка
  • тело сообщения (body)
  • завершающий символ NULL (\0)

Главная особенность версии — максимальная простота парсинга. Все данные передаются как UTF-8 текст без сложных правил экранирования.

Поддержка ACK

В STOMP 1.0 подтверждение сообщений реализовано через заголовок ack:

  • auto — автоматическое подтверждение
  • client — ручное подтверждение

Однако механизм был ограничен: отсутствовала точная идентификация сообщений через ack id, что усложняло надёжную обработку очередей.

Ограничения версии

STOMP 1.0 имел ряд архитектурных ограничений:

  • отсутствие heartbeat-механизма
  • отсутствие обязательного заголовка host
  • слабая формализация соединения
  • отсутствие расширенной модели транзакций

Эти ограничения привели к появлению STOMP 1.1.

STOMP 1.1

STOMP 1.1 стал важной эволюцией протокола, добавив поддержку более строгой идентификации соединений и базовую инфраструктуру для стабильных долгоживущих соединений.

Заголовок host

Одним из ключевых изменений стало обязательное использование заголовка:

host: example.com

Это позволило одному брокеру обслуживать несколько виртуальных хостов и стало критически важным для масштабируемых систем.

Heart-beat механизм

STOMP 1.1 вводит heartbeat — механизм контроля живости соединения.

Он задаётся в заголовке heart-beat при CONNECT:

heart-beat: cx,cy

где:

  • cx — интервал отправки данных клиентом
  • cy — интервал ожидания данных от сервера

Принцип работы:

  • клиент и сервер договариваются о минимальных интервалах
  • при отсутствии данных отправляются пустые байты (keep-alive)
  • при нарушении интервалов соединение считается разорванным

STOMP.js использует heartbeat для автоматического контроля соединения поверх WebSocket.

Улучшенная модель ACK

В STOMP 1.1 появляется ack id, позволяющий точно идентифицировать сообщение:

ack: client
message-id: 123

Появляется возможность:

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

Расширенные заголовки

STOMP 1.1 допускает более строгую интерпретацию заголовков:

  • запрещены неоднозначные значения
  • улучшена спецификация кодирования
  • усиливается совместимость между брокерами

STOMP 1.2

STOMP 1.2 является наиболее стабильной и широко используемой версией протокола. Она устраняет неоднозначности предыдущих версий и вводит строгие правила совместимости.

Обязательный NUL-терминатор

Формат фрейма сохраняется, но строго регламентируется завершение:

COMMAND
header:value

body\0

Особое внимание уделяется тому, что NULL-символ является единственным корректным завершением кадра.

Экранирование символов

В STOMP 1.2 вводится строгая система экранирования заголовков:

  • \r\\r
  • \n\\n
  • :\\c
  • \\\\

Это устраняет неоднозначности при передаче бинарных или сложных текстовых данных в заголовках.

Heart-beat с уточнённой логикой

В 1.2 heartbeat становится более предсказуемым:

  • чёткое разделение входящего и исходящего интервала
  • отказ от отправки heartbeat при активном трафике
  • унифицированная обработка таймаутов

CONNECT и CONNECTED улучшения

В STOMP 1.2 расширяются правила рукопожатия:

CONNECT теперь может включать:

  • accept-version: 1.2
  • host
  • heart-beat

Ответ CONNECTED содержит:

  • фактическую версию протокола
  • согласованные параметры heartbeat

Это позволяет STOMP.js автоматически выбирать совместимый режим работы.

Улучшения ACK/NACK

Появляется поддержка NACK:

  • явный отказ от сообщения
  • возможность повторной доставки
  • улучшенная интеграция с брокерами очередей

Также усиливается модель транзакций:

  • BEGIN
  • COMMIT
  • ABORT

Сравнение версий

Поддержка ключевых возможностей

  • STOMP 1.0: базовые сообщения, без heartbeat
  • STOMP 1.1: heartbeat, host, улучшенный ACK
  • STOMP 1.2: строгие правила, экранирование, NACK, стабильность

Поведение соединения

  • 1.0: простое TCP-подобное соединение без контроля
  • 1.1: контроль живости соединения через heartbeat
  • 1.2: детерминированная модель соединения с формализованными таймаутами

Совместимость STOMP.js

STOMP.js реализует поддержку всех трёх версий, но фактическая работа зависит от брокера:

  • WebSocket брокеры чаще используют 1.2
  • старые JMS-брокеры могут ограничиваться 1.0 или 1.1

При инициализации клиента STOMP.js версия указывается явно:

Stomp.client(url, {
  protocols: ['v10.stomp', 'v11.stomp', 'v12.stomp']
});

или через negotiate:

client.connectHeaders = {
  'accept-version': '1.2'
};

Совместимость и миграция

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

Переход с 1.0 на 1.1

Критические изменения:

  • добавление обязательного host
  • появление heartbeat
  • необходимость обработки message-id

Переход с 1.1 на 1.2

Основные изменения:

  • строгие правила экранирования
  • поддержка NACK
  • более жёсткая спецификация кадров
  • улучшенная обработка ошибок парсинга

Поведение STOMP.js при fallback

STOMP.js обычно:

  • сначала пытается 1.2
  • при отказе переключается на 1.1
  • затем на 1.0

Это обеспечивает совместимость с различными брокерами без ручной настройки.

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

Выбор версии при CONNECT

Клиент формирует список поддерживаемых версий:

  • 1.0
  • 1.1
  • 1.2

Брокер выбирает максимально совместимую.

Обработка heartbeat

STOMP.js использует внутренние таймеры:

  • отправка пустых кадров или LF
  • контроль интервалов входящих сообщений
  • автоматическое закрытие при таймауте

Парсинг фреймов

Различия версий влияют на:

  • экранирование заголовков
  • допустимость пустых строк
  • обработку тела сообщения

Особенно критично в 1.2, где ошибки экранирования могут приводить к некорректному разбору всего фрейма.

ACK/NACK логика

В STOMP.js подтверждение сообщений реализуется через:

  • message.ack()
  • message.nack()

Поведение зависит от версии протокола и брокера, но библиотека абстрагирует различия, сохраняя единый API.

Практическое влияние версий на архитектуру приложений

Выбор версии протокола влияет на:

  • устойчивость соединения в условиях нестабильной сети
  • нагрузку на брокер сообщений
  • точность доставки сообщений
  • поведение retry-механизмов

STOMP 1.2 становится предпочтительным в системах с высокой нагрузкой и требованиями к надёжности доставки, тогда как 1.0 встречается только в устаревших интеграциях.