В STOMP-протоколе отсутствует единое строго обязательное поле для управления временем жизни сообщения, однако большинство брокеров реализуют поддержку TTL через заголовки сообщения. В контексте STOMP.js TTL реализуется через передачу специальных headers при отправке сообщения, которые затем интерпретируются брокером (например, ActiveMQ, RabbitMQ, Apollo, Artemis).
Основная идея TTL заключается в ограничении времени существования сообщения в очереди. Если сообщение не было доставлено потребителю за заданный интервал, оно либо удаляется, либо перенаправляется в dead-letter queue (DLQ), в зависимости от конфигурации брокера.
Ключевой момент: STOMP.js не реализует TTL самостоятельно — он лишь передаёт метаданные, а вся логика исполнения находится на стороне брокера.
В зависимости от брокера используются разные заголовки:
expiration — абсолютное время истечения сообщения (в
миллисекундах epoch time)time-to-live — относительное время жизни сообщенияmessage-ttl — часто используется в RabbitMQ через
headers или queue argumentsНа практике наиболее универсальным является заголовок
expiration.
При использовании STOMP.js TTL задаётся через объект headers в методе
publish или send.
client.publish({
destination: "/queue/orders",
body: JSON.stringify({ orderId: 123 }),
headers: {
expiration: (Date.now() + 10000).toString()
}
});
В этом примере сообщение будет действительно только 10 секунд. После этого брокер может удалить его, если оно не было доставлено.
STOMP-протокол не стандартизирует относительный TTL напрямую, поэтому он эмулируется вычислением абсолютного времени:
const ttl = 30_000; // 30 секунд
client.publish({
destination: "/queue/notifications",
body: JSON.stringify({ text: "Hello" }),
headers: {
expiration: String(Date.now() + ttl)
}
});
Подобный подход используется во всех клиентских реализациях STOMP.js независимо от версии.
В RabbitMQ TTL может задаваться тремя способами:
STOMP.js в этом случае передаёт только headers, а брокер интерпретирует их:
client.publish({
destination: "/queue/task",
body: "data",
headers: {
"expiration": String(Date.now() + 60000)
}
});
На стороне RabbitMQ это соответствует per-message TTL.
В ActiveMQ поддерживаются:
time-to-liveJMSExpiration (внутренний аналог expiration)Пример:
client.publish({
destination: "/queue/jobs",
body: "process",
headers: {
"time-to-live": "45000"
}
});
Однако фактическая поддержка зависит от STOMP adapter слоя брокера.
Когда TTL истекает, поведение зависит от конфигурации брокера:
Удаление без следа Сообщение просто удаляется из очереди без уведомления клиента.
Перемещение в Dead Letter Queue Используется в системах с критичной доставкой сообщений.
Переотправка или логирование Некоторые брокеры могут логировать истечение TTL.
Важно учитывать, что STOMP.js не получает обратного уведомления о том, что сообщение истекло.
TTL тесно связан с механизмом подтверждений:
ACK) до истечения
TTL, оно считается просроченнымclient.ack() TTL уже не играет ролиclient.nack() сообщение может быть возвращено в
очередь, если TTL не истёкПример подписки:
client.subscribe("/queue/tasks", (message) => {
const data = JSON.parse(message.body);
processTask(data);
message.ack();
});
Если ack() не вызван и TTL истекает, сообщение может
быть удалено брокером.
TTL используется для предотвращения доставки устаревших уведомлений:
client.publish({
destination: "/queue/alerts",
body: "system update",
headers: {
expiration: String(Date.now() + 15000)
}
});
В системах фоновой обработки TTL предотвращает выполнение устаревших задач:
TTL ограничивает доставку сообщений, если клиент долго был офлайн:
Некоторые брокеры требуют строковый формат:
headers: {
expiration: Date.now().toString()
}
TTL очереди задаётся при создании queue и не изменяется через STOMP.js:
При высокой нагрузке сообщение может истечь до обработки:
В распределённых архитектурах TTL используется как механизм защиты от:
STOMP.js в таких системах выступает лишь транспортным слоем, а TTL становится частью общей политики маршрутизации сообщений.
Наличие TTL влияет на:
В некоторых брокерах массовое использование TTL может приводить к дополнительным накладным расходам на проверку истечения срока жизни сообщений.
При использовании транзакций:
client.begin();
client.publish({
destination: "/queue/tx",
body: "data",
headers: {
expiration: String(Date.now() + 20000)
}
});
client.commit();
Разные брокеры интерпретируют TTL по-разному:
STOMP.js не нормализует эти различия, поэтому поведение всегда зависит от серверной стороны.
В системах с высокой скоростью сообщений TTL может использоваться как фильтр потока:
Это особенно важно в: