История протокола

В начале 2000-х годов активно развивались системы обмена сообщениями и брокеры очередей. Корпоративные приложения increasingly строились вокруг асинхронного взаимодействия: сервисы отправляли события, очереди распределяли задачи, а серверы обменивались данными без прямой синхронной связи.

На рынке уже существовали крупные решения:

  • IBM с системой MQ;
  • TIBCO;
  • Oracle;
  • Apache Software Foundation с ActiveMQ.

Однако большинство брокеров использовали собственные бинарные протоколы. Это создавало несколько серьёзных проблем:

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

В этот период активно развивались текстовые сетевые протоколы:

  • HTTP;
  • SMTP;
  • FTP;
  • IRC.

Они были популярны благодаря простоте анализа и независимости от платформы. Разработчики могли открыть telnet-сессию и вручную взаимодействовать с сервером.

На фоне этих идей возникла концепция простого текстового протокола для брокеров сообщений.


Рождение STOMP

STOMP расшифровывается как:

Simple Text Oriented Messaging Protocol

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

Первоначально STOMP разрабатывался как альтернатива сложным бинарным протоколам. Основная идея заключалась в следующем:

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

Одним из ранних центров развития STOMP стал брокер сообщений:

Apache ActiveMQ

Именно вокруг него сформировалось активное сообщество пользователей STOMP.


Основные идеи архитектуры STOMP

Создатели протокола сознательно отказались от сложной архитектуры.

В основе STOMP лежали несколько принципов.

Текстовый формат кадров

Каждое сообщение представлялось как текстовый фрейм:

SEND
destination:/queue/test

Hello World

Такой формат был легко читаем человеком.

Для сравнения:

  • бинарные протоколы требовали специальных библиотек;
  • STOMP можно было анализировать обычным сетевым сниффером.

Минимальный набор команд

STOMP содержал небольшой набор операций:

  • CONNECT;
  • SEND;
  • SUBSCRIBE;
  • UNSUBSCRIBE;
  • ACK;
  • NACK;
  • DISCONNECT.

Это резко снижало порог входа.


Независимость от платформы

STOMP не был привязан к:

  • Java;
  • .NET;
  • C++;
  • конкретному брокеру сообщений.

Любой язык с TCP-сокетами мог реализовать клиента.


Простота реализации

Реализация клиента STOMP занимала сравнительно мало кода.

Это сделало протокол популярным среди:

  • веб-разработчиков;
  • embedded-разработчиков;
  • интеграторов;
  • DevOps-инженеров.

Связь STOMP и JMS

Важную роль в распространении STOMP сыграла технология:

Java Message Service

JMS являлся стандартом обмена сообщениями в экосистеме Java EE.

Проблема заключалась в том, что:

  • JMS был API, а не сетевым протоколом;
  • для работы требовалась Java;
  • межъязыковая интеграция оставалась сложной.

STOMP стал своеобразным мостом между JMS-брокерами и внешними системами.

Например:

  • Java-сервис мог использовать JMS;
  • JavaScript-клиент подключался через STOMP;
  • оба взаимодействовали через один брокер сообщений.

Именно это сделало STOMP особенно востребованным.


Развитие брокеров сообщений и роль ActiveMQ

Одним из ключевых этапов истории STOMP стало развитие:

Apache ActiveMQ

ActiveMQ активно продвигал идею мультипротокольности.

Брокер поддерживал:

  • OpenWire;
  • STOMP;
  • AMQP;
  • MQTT;
  • XMPP.

Поддержка STOMP позволила подключать клиентов практически на любом языке.

Например:

  • PHP;
  • Python;
  • Ruby;
  • Perl;
  • JavaScript.

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


Эволюция версий STOMP

История протокола делится на несколько этапов.

STOMP 1.0

Первая версия была предельно простой.

Основные особенности:

  • базовые команды;
  • отсутствие heartbeat;
  • минимальная обработка ошибок;
  • простые подписки.

Версия хорошо подходила для локальных сетей, но имела ограничения при нестабильных соединениях.


STOMP 1.1

Следующая версия значительно расширила возможности протокола.

Появились:

  • heartbeat-механизм;
  • подтверждение ACK/NACK;
  • улучшенная работа с подписками;
  • идентификаторы подписок;
  • обработка версий протокола.

Heartbeat стал особенно важным.

Он позволял:

  • обнаруживать обрыв соединения;
  • поддерживать long-lived TCP connections;
  • уменьшать вероятность “зависших” клиентов.

STOMP 1.2

Версия 1.2 стала наиболее зрелой редакцией протокола.

Были уточнены:

  • правила обработки заголовков;
  • escape-последовательности;
  • работа с CRLF;
  • семантика ACK;
  • требования к совместимости.

Именно STOMP 1.2 чаще всего используется сегодня.


Появление WebSocket и новая популярность STOMP

Настоящий взрыв популярности STOMP произошёл после появления технологии:

WebSocket

До WebSocket браузеры имели серьёзные ограничения:

  • polling;
  • long polling;
  • iframe hacks;
  • высокая задержка;
  • лишний HTTP-overhead.

WebSocket изменил модель взаимодействия браузера с сервером.

Появилось полноценное двустороннее соединение.

На этом фоне STOMP оказался практически идеальным кандидатом для браузерных real-time приложений.

Причины были очевидны:

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

Возникновение STOMP.js

С распространением WebSocket появилась необходимость в JavaScript-клиентах STOMP.

Так возникла библиотека:

STOMP.js

Её задачей стало предоставление удобного API для браузеров.

Библиотека скрывала сложность:

  • формирования кадров;
  • reconnection logic;
  • heartbeat;
  • сериализации сообщений;
  • подписок.

Разработчик мог работать с высокоуровневым API вместо ручного формирования STOMP-фреймов.


Ранние версии STOMP.js

Первые версии библиотеки были достаточно простыми.

Типичный код выглядел следующим образом:

const socket = new WebSocket('ws://localhost:15674/ws');

const client = Stomp.over(socket);

client.connect({}, () => {
    client.subscribe('/queue/test', message => {
        console.log(message.body);
    });

    client.send('/queue/test', {}, 'Hello');
});

Такой API быстро стал популярным благодаря:

  • простоте;
  • малому объёму кода;
  • хорошей совместимости;
  • интеграции с брокерами.

Распространение RabbitMQ и влияние на STOMP

Большую роль в развитии STOMP сыграл брокер:

RabbitMQ

RabbitMQ активно развивался в экосистеме Erlang и поддерживал множество протоколов через плагины.

Поддержка STOMP позволила использовать:

  • браузерные клиенты;
  • Node.js;
  • мобильные приложения;
  • лёгкие сервисы интеграции.

Особенно популярной стала схема:

Browser -> WebSocket -> STOMP -> RabbitMQ

Эта архитектура активно использовалась:

  • в чатах;
  • системах уведомлений;
  • торговых терминалах;
  • системах мониторинга;
  • multiplayer-приложениях.

Эпоха real-time веб-приложений

В 2010-х годах рынок начал переходить к real-time интерфейсам.

Появились:

  • live-чаты;
  • push-уведомления;
  • совместное редактирование;
  • online dashboards;
  • streaming UI.

STOMP.js стал важным элементом этой архитектуры.

Особенно в сочетании с:

  • WebSocket;
  • SockJS;
  • Spring;
  • RabbitMQ;
  • ActiveMQ.

Интеграция со Spring Framework

Огромное влияние на популярность STOMP оказала экосистема:

Spring Framework

Spring добавил встроенную поддержку:

  • STOMP over WebSocket;
  • брокеров сообщений;
  • pub/sub-модели;
  • endpoint mapping.

Типичная архитектура выглядела следующим образом:

Browser
   ↓
STOMP.js
   ↓
WebSocket
   ↓
Spring WebSocket
   ↓
Message Broker

После этого STOMP фактически стал стандартом real-time взаимодействия в Java-экосистеме.


Эволюция самой библиотеки STOMP.js

С течением времени библиотека проходила несколько этапов модернизации.

Ранний API

Первые версии использовали callback-style API:

client.connect(headers, onConnect, onError);

Переход к современному JavaScript

Позже библиотека была адаптирована под:

  • ES6;
  • TypeScript;
  • модульную архитектуру;
  • npm;
  • bundlers.

Появление @stomp/stompjs

Современная библиотека получила пакет:

@stomp/stompjs

Он стал официальным развитием старого stompjs.

Появились:

  • TypeScript typings;
  • auto reconnect;
  • improved heartbeat;
  • async lifecycle;
  • better browser support.

Изменение роли STOMP в современной архитектуре

Со временем рынок messaging-протоколов изменился.

Появились новые стандарты:

  • AMQP;
  • MQTT;
  • Kafka Protocol;
  • gRPC streams.

Однако STOMP сохранил популярность благодаря нескольким особенностям.

Простота

Протокол остаётся крайне понятным.

Даже raw STOMP-frame можно прочитать глазами.


Удобство для браузеров

Текстовая модель отлично сочетается с WebSocket.


Низкий порог входа

STOMP проще многих enterprise-протоколов.


Хорошая интеграция с Java

Spring и ActiveMQ продолжают активно использовать STOMP.


Отличия STOMP от AMQP

Исторически STOMP часто сравнивали с:

Advanced Message Queuing Protocol

Основные различия:

STOMP AMQP
Текстовый Бинарный
Простой Более сложный
Минимум команд Богатая модель
Лёгкая реализация Сложный стек
Подходит для браузеров Лучше для enterprise integration

AMQP предоставляет:

  • маршрутизацию;
  • exchanges;
  • transactions;
  • сложную доставку.

STOMP же делает ставку на простоту.


Современное состояние STOMP.js

Сегодня STOMP.js применяется в:

  • SPA-приложениях;
  • административных панелях;
  • системах мониторинга;
  • финансовых dashboards;
  • корпоративных чатах;
  • online gaming backend;
  • IoT dashboards.

Современные версии библиотеки поддерживают:

  • automatic reconnect;
  • heartbeat;
  • binary payloads;
  • TypeScript;
  • WebSocket abstraction;
  • debug logging.

Причины долговечности протокола

Несмотря на возраст, STOMP продолжает использоваться благодаря нескольким причинам.

Человеко-читаемый формат

Текстовые фреймы удобно:

  • отлаживать;
  • логировать;
  • анализировать.

Простая реализация

Даже минимальный клиент может быть реализован за короткое время.


Совместимость

STOMP поддерживается большим количеством брокеров:

  • RabbitMQ;
  • ActiveMQ;
  • Apollo;
  • HornetQ;
  • Artemis.

Хорошая интеграция с вебом

Исторически именно WebSocket дал STOMP вторую жизнь.

Без WebSocket протокол, вероятно, остался бы нишевым решением для интеграции брокеров.


Историческое значение STOMP.js

STOMP.js сыграл важную роль в развитии real-time веб-приложений.

До появления современных streaming-платформ библиотека стала одним из первых массовых способов организации:

  • push-архитектуры;
  • pub/sub-модели;
  • браузерных подписок;
  • event-driven frontend.

Во многих enterprise-системах STOMP.js до сих пор остаётся стандартным способом интеграции браузера с message broker-инфраструктурой.