ActiveMQ Artemis

Архитектурная модель взаимодействия

Apache ActiveMQ Artemis реализует многопротокольный брокер сообщений с поддержкой STOMP, AMQP, MQTT и собственного Core-протокола. В связке с веб-клиентами наиболее часто используется STOMP поверх WebSocket, где клиентская сторона реализуется через STOMP.js.

Общая схема выглядит следующим образом:

  • браузерное приложение
  • STOMP.js клиент
  • WebSocket соединение
  • STOMP Acceptor в Artemis
  • адреса (addresses) и очереди (queues)
  • потребители (consumers) и продюсеры (producers)

Ключевой момент заключается в том, что STOMP в Artemis не является нативным протоколом маршрутизации сообщений, а транслируется в внутреннюю модель адресов и очередей брокера.


Настройка STOMP Acceptor в Artemis

Для работы STOMP через WebSocket в Artemis необходимо включить соответствующий acceptor в broker.xml.

Основной пример конфигурации:

<acceptors>
    <acceptor name="stomp-websocket">
        tcp://0.0.0.0:61613?protocols=STOMP;ws.stompPort=61614
    </acceptor>
</acceptors>

Дополнительно можно разделить WebSocket-слой:

<acceptor name="stomp-ws">
    tcp://0.0.0.0:61613?protocols=STOMP
</acceptor>

<acceptor name="stomp-ws-websocket">
    tcp://0.0.0.0:61614?protocols=STOMP;useWebSockets=true
</acceptor>

Важные параметры acceptor:

  • protocols=STOMP — включение STOMP
  • useWebSockets=true — активация WebSocket транспорта
  • ws.stompPort — порт для WebSocket подключения
  • tcp://0.0.0.0 — биндинг на все интерфейсы

Модель адресов и очередей в Artemis

Apache ActiveMQ Artemis использует концепцию address → queue mapping.

STOMP-клиент не работает напрямую с очередями Artemis, он использует:

  • destination /topic/… → multicast routing
  • destination /queue/… → anycast routing

ANYCAST (очередь)

  • сообщение доставляется одному потребителю
  • используется для job processing

MULTICAST (топик)

  • сообщение получают все подписчики
  • используется для pub/sub

Подключение STOMP.js к Artemis через WebSocket

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

Пример подключения:

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

const client = new Client({
  brokerURL: 'ws://localhost:61614/stomp',
  reconnectDelay: 5000,
  heartbeatIncoming: 4000,
  heartbeatOutgoing: 4000,
});

Аутентификация в Artemis

Artemis поддерживает простую файловую модель пользователей:

etc/login.config и etc/artemis-users.properties:

admin = admin
user = password

В STOMP.js:

const client = new Client({
  brokerURL: 'ws://localhost:61614/stomp',
  connectHeaders: {
    login: 'user',
    passcode: 'password'
  }
});

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

Очередь (ANYCAST)

client.onConn ect = () => {
  client.subscribe('/queue/orders', (message) => {
    console.log('Order:', message.body);
    message.ack();
  }, {
    ack: 'client-individual'
  });
};

Топик (MULTICAST)

client.subscribe('/topic/notifications', (message) => {
  console.log('Notification:', message.body);
});

Механизмы подтверждения (ACK)

Artemis поддерживает несколько режимов ACK:

  • auto
  • client
  • client-individual

client ACK

message.ack();

client-individual ACK

message.ack();

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


Отправка сообщений в Artemis через STOMP.js

client.publish({
  destination: '/queue/orders',
  body: JSON.stringify({
    orderId: 123,
    status: 'created'
  }),
  headers: {
    persistent: 'true'
  }
});

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

Apache ActiveMQ Artemis поддерживает сохранение сообщений в журнал (journal storage).

В STOMP можно управлять поведением через заголовки:

  • persistent: true
  • priority: 0–9
  • expiration: timestamp

Пример:

client.publish({
  destination: '/queue/orders',
  body: 'Important message',
  headers: {
    persistent: 'true',
    priority: '9',
    expiration: Date.now() + 60000
  }
});

Heartbeats и контроль соединения

STOMP.js позволяет контролировать живость соединения:

const client = new Client({
  brokerURL: 'ws://localhost:61614/stomp',
  heartbeatIncoming: 10000,
  heartbeatOutgoing: 10000
});

Artemis отвечает heartbeat-фреймами, предотвращая разрыв idle-соединений через прокси и балансировщики.


Транзакции в STOMP

Artemis поддерживает транзакционную модель STOMP.

client.begin();

client.publish({
  destination: '/queue/orders',
  body: 'tx message'
});

client.commit();

Rollback:

client.abort();

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


Управление потоками сообщений и backpressure

Artemis ограничивает скорость доставки через:

  • prefetch-size
  • consumer window size
  • credits-based flow control

STOMP.js косвенно участвует через настройки подписки:

client.subscribe('/queue/orders', callback, {
  'prefetch-size': '50'
});

Durable subscriptions (устойчивые подписки)

Для топиков можно использовать durable subscriptions:

client.subscribe('/topic/events', callback, {
  durable: 'true',
  'client-id': 'app-1',
  id: 'sub-1'
});

Artemis сохраняет состояние подписки и доставляет сообщения после переподключения.


Роутинг сообщений в Artemis при STOMP

STOMP destination трансформируется в internal address:

  • /queue/orders → address orders, queue orders
  • /topic/events → address events, multicast queue set

Artemis использует routing type:

  • ANYCAST
  • MULTICAST

Это влияет на поведение доставки независимо от STOMP клиента.


Ошибки и обработка disconnect

STOMP.js предоставляет события жизненного цикла:

client.onStompEr ror = (frame) => {
  console.error('Broker error', frame.headers['message']);
};

client.onWebSocketCl ose = () => {
  console.log('Connection closed');
};

Artemis может отправлять ERROR frame при:

  • неверной аутентификации
  • отсутствии destination
  • превышении лимитов ресурсов

Security и permissions

Artemis управляет доступом через role-based security:

<security-setting match="queue.orders">
    <permission type="send" roles="user"/>
    <permission type="consume" roles="user"/>
</security-setting>

STOMP клиент наследует ограничения брокера, и попытка подписки без прав приводит к ERROR frame.


Оптимизация работы STOMP.js с Artemis

Ключевые практики:

  • использование persistent сообщений только для критичных данных
  • ограничение размера payload
  • применение ack: client-individual для контроля доставки
  • настройка reconnectDelay для устойчивости WebSocket
  • использование topic/queue строго по назначению routing type

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

WebSocket acceptor в Artemis работает как транспортная обертка:

  • переводит binary/text frames в STOMP frames
  • управляет сессиями клиентов
  • связывает connection → consumer lifecycle

При разрыве WebSocket Artemis автоматически освобождает consumer и может сохранить state durable subscription.


Логическая модель взаимодействия

  • STOMP.js формирует STOMP frames
  • WebSocket передает кадры брокеру
  • Artemis маршрутизирует через address model
  • очередь/топик выполняет delivery semantics
  • ACK подтверждает обработку
  • journal обеспечивает устойчивость данных

Эта цепочка обеспечивает сквозную доставку сообщений от браузера до брокера с контролируемой надежностью и масштабированием.