Приоритеты сообщений

Модель приоритетов в протоколе STOMP

Протокол STOMP (Simple Text Oriented Messaging Protocol) определяет механизм передачи сообщений между клиентом и брокером, однако сам по себе не навязывает строгую модель приоритетов доставки. Поддержка приоритетов реализуется на уровне брокера сообщений, а не клиентской библиотеки.

В STOMP приоритет задаётся через заголовок сообщения:

priority: <число от 0 до 9>

Ключевые особенности:

  • Диапазон значений обычно от 0 (низший приоритет) до 9 (наивысший)
  • Значение носит рекомендательный характер
  • Реальная обработка зависит от брокера (ActiveMQ, RabbitMQ, Artemis и др.)
  • STOMP.js лишь передаёт заголовок, не интерпретируя его

Роль STOMP.js в работе с приоритетами

Библиотека STOMP.js выполняет исключительно транспортную функцию:

  • формирует STOMP frame
  • добавляет заголовки
  • отправляет сообщение через WebSocket или другой транспорт

STOMP.js не управляет очередями и не сортирует сообщения.

Пример отправки сообщения с приоритетом:

import { Client } from '@stomp/stompjs';

const client = new Client({
  brokerURL: 'ws://localhost:15674/ws',
  reconnectDelay: 5000
});

client.onConn ect = () => {
  client.publish({
    destination: '/queue/orders',
    body: JSON.stringify({ orderId: 123 }),
    headers: {
      priority: '7'
    }
  });
};

client.activate();

В этом примере значение priority: '7' передаётся брокеру, который уже решает, как его интерпретировать.


Поддержка приоритетов в брокерах сообщений

Разные брокеры по-разному реализуют обработку приоритетов.

ActiveMQ / Artemis

В ActiveMQ и Artemis приоритеты поддерживаются на уровне очередей:

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

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

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

В RabbitMQ поддержка приоритетов зависит от типа очереди:

  • classic queues поддерживают priority queues
  • нужно явно включать параметр x-max-priority
  • без настройки заголовок priority игнорируется

Пример конфигурации очереди:

channel.assertQueue('tasks', {
  arguments: {
    'x-max-priority': 10
  }
});

Поведение доставки и влияние приоритетов

Приоритет влияет только на порядок извлечения сообщений из очереди, но не на:

  • скорость сетевой доставки
  • время публикации
  • гарантии доставки (ACK/NACK)
  • маршрутизацию сообщений

Важно: Приоритет не является механизмом QoS, он не гарантирует мгновенную обработку.


Формат и семантика заголовка priority

STOMP определяет заголовки как строковые пары ключ-значение. Поэтому:

headers: {
  priority: '9'
}

или

headers: {
  priority: 9
}

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

Стандартная интерпретация:

  • 0–3 — низкий приоритет
  • 4–6 — средний
  • 7–9 — высокий

Однако конкретная градация не регламентирована протоколом.


Очерёдность обработки сообщений с приоритетами

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

  1. Сначала выбираются сообщения с максимальным priority
  2. Внутри одного уровня сохраняется FIFO (если брокер так реализован)
  3. При переполнении очереди возможны оптимизации, нарушающие строгий порядок

Пример логики:

Очередь:
  A (priority 3)
  B (priority 9)
  C (priority 5)

Доставка:
  B → C → A

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

Несмотря на наличие механизма, существуют фундаментальные ограничения:

  • STOMP.js не гарантирует обработку приоритетов
  • не все брокеры поддерживают priority queues
  • приоритет не влияет на уже доставленные сообщения
  • консистентность порядка не гарантируется при масштабировании consumer group

Влияние acknowledgement на приоритеты

Режим подтверждения сообщений (ACK) может влиять на наблюдаемое поведение приоритетов.

client.subscribe('/queue/tasks', message => {
  // обработка
  message.ack();
}, { ack: 'client-individual' });

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

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

Приоритеты и конкурентные подписчики

При нескольких подписчиках на одну очередь:

  • брокер распределяет сообщения между consumers
  • приоритет работает внутри очереди, но не между consumers напрямую
  • возможен эффект «голодания» низкоприоритетных сообщений при высокой нагрузке

Сценарий:

Consumer A: быстрый
Consumer B: медленный

Высокий priority:
  уходит A и B
Низкий priority:
  может обрабатываться только B или откладываться

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

Приоритеты обычно применяются в системах:

  • обработки задач (task queues)
  • системах уведомлений
  • обработке платежей
  • очередях событий с разным уровнем важности

Типичная схема:

client.publish({
  destination: '/queue/payments',
  body: JSON.stringify(payment),
  headers: {
    priority: payment.isUrgent ? '9' : '4'
  }
});

Совместимость STOMP версии и приоритетов

STOMP 1.0, 1.1 и 1.2 не вносят существенных изменений в модель приоритетов. Отличия касаются:

  • формата frame
  • заголовков безопасности
  • heart-beat механизма

Приоритет остаётся пользовательским заголовком.


Ошибки и типичные проблемы

  1. Priority игнорируется брокером

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

    • многопоточность consumers
    • горизонтальное масштабирование
  3. Ожидание строгого приоритета

    • ошибка архитектурного уровня
    • STOMP не гарантирует строгую сортировку глобально
  4. Передача некорректных значений

    • строки вне диапазона 0–9
    • отрицательные числа
    • нечисловые значения

Взаимодействие STOMP.js с брокерными политиками

STOMP.js не знает о:

  • типе очереди
  • политике планирования сообщений
  • внутреннем scheduler брокера

Он передаёт только структуру:

SEND
destination:/queue/example
priority:5

<payload>

Вся дальнейшая логика находится вне клиента.


Архитектурные выводы по использованию приоритетов

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

В системах с высокой конкуренцией сообщений приоритеты часто комбинируются с:

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