Формат адресов назначения

В STOMP адрес назначения (destination) представляет собой строковый идентификатор канала доставки сообщений между клиентом и брокером. Он не является объектом или структурой данных, а строго интерпретируется серверной частью маршрутизации сообщений. Формат строки определяется соглашениями конкретного брокера, но в большинстве реализаций сохраняется общая логика: адрес описывает логический путь доставки сообщения к подписчикам или обработчикам.

Ключевая особенность заключается в том, что STOMP не навязывает единый стандарт структуры адресов, оставляя это на уровень брокера сообщений. В результате одинаковые STOMP-клиенты могут работать с различными схемами маршрутизации без изменений в коде, но с различными правилами формирования destination.


Иерархическая структура и соглашения именования

Адрес назначения почти всегда строится как иерархический путь, похожий на файловую систему. Используются разделители, чаще всего символ /, формируя логические категории.

Типичная форма:

/segment/subsegment/identifier

Такая структура применяется для упрощения группировки сообщений и фильтрации подписок.

Примеры:

/topic/chat/general
/queue/orders.processing
/app/events/user.created

Каждый сегмент несет смысловую нагрузку:

  • первый уровень — тип маршрута или домен
  • второй уровень — область системы
  • последующие уровни — уточнение контекста

Основные типы адресов: topic и queue

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

Топики (publish/subscribe)

Адреса типа topic используются для широковещательной модели, где одно сообщение получают все подписчики.

Пример:

/topic/news
/topic/notifications.system

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

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

Очереди (point-to-point)

Адреса queue реализуют модель индивидуальной доставки, где сообщение получает один потребитель.

Пример:

/queue/tasks
/queue/payments.process

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

  • сообщение обрабатывается одним consumer’ом
  • поддерживается балансировка нагрузки
  • применяется для фоновых задач и обработки данных

Пользовательские назначения и персональные каналы

В STOMP существует механизм пользовательских destinations, позволяющий доставлять сообщения конкретному клиенту.

Часто используется префикс:

/user/queue/...

Примеры:

/user/queue/notifications
/user/queue/private.messages

Такие адреса не привязаны к глобальной очереди или топику. Брокер выполняет дополнительное сопоставление на основе сессии, идентификатора пользователя или токена авторизации.

В серверных реализациях (например, Spring-based брокерах) пользовательский destination преобразуется в внутренний уникальный канал, связанный с конкретным соединением.


Префиксы приложений и брокера

Во многих архитектурах STOMP используется разделение пространства имён на уровне префиксов.

Наиболее распространённая схема:

  • /app — сообщения, отправляемые в серверную логику (application destination)
  • /topic — публикация событий
  • /queue — очереди задач
  • /user — персональные каналы

Пример маршрутизации:

/app/order.create   → обработка на сервере
/topic/order.events → рассылка всем клиентам
/queue/order.jobs   → очередь обработки

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


Формальные ограничения и особенности строки destination

Хотя STOMP не накладывает строгих ограничений на формат строки, на практике применяются следующие правила:

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

Некоторые брокеры дополнительно поддерживают:

  • * как wildcard для одного сегмента
  • ** для множественных сегментов
  • параметризацию через {variable}

Пример шаблонов:

/topic/chat.*
/queue/orders.**
/topic/user.{id}.events

Однако поддержка таких выражений не является частью STOMP-спецификации и определяется конкретной реализацией.


Механика подписки в STOMP.js

В STOMP.js destination передаётся как строка при подписке:

client.subscribe("/topic/chat/general", (message) => {
  console.log(message.body);
});

И при отправке:

client.publish({
  destination: "/app/message.send",
  body: JSON.stringify({ text: "hello" })
});

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


Пространства имён в распределённых системах

В сложных системах destination становится частью глобальной схемы маршрутизации. Для предотвращения конфликтов используется доменное именование:

/topic/{domain}/{service}/{event}
/queue/{service}/{task}
/app/{module}/{command}

Пример:

/topic/billing/invoices.created
/queue/auth/password.reset
/app/user/profile.update

Такой подход обеспечивает:

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

Особенности интерпретации в разных брокерах

Разные брокеры по-разному трактуют одинаковые destination:

  • RabbitMQ через STOMP адаптер может маппить topic/queue на exchange и routing key
  • ActiveMQ использует JMS-совместимую модель с собственными правилами именования
  • Spring Message Broker добавляет слой абстракции над destination

Из-за этого одна и та же строка:

/topic/chat.general

может соответствовать разным внутренним механизмам доставки.


Ошибки проектирования адресов назначения

Некорректная структура destination часто приводит к проблемам масштабирования и поддержки системы.

Типичные ошибки:

Использование плоской структуры без иерархии:

/chat1
/chat2
/chat3

Смешивание типов сообщений в одном пространстве:

/data

Отсутствие разделения команд и событий:

/messages

Перегруженные длинные пути без семантики:

/app/v1/user/profile/settings/update/request/confirmed

Такие подходы затрудняют маршрутизацию, фильтрацию и сопровождение системы.


Роль destination в архитектуре событий

Destination выступает связующим слоем между клиентской логикой и брокером сообщений. Он определяет не только маршрут доставки, но и архитектурную структуру всей системы обмена сообщениями. Через корректно спроектированные адреса формируется модель взаимодействия между сервисами, пользователями и событиями, где каждая строка становится частью общей схемы распределённой коммуникации.