#java #rabbitmq #amqp #spring-rabbit #spring-amqp
#java #rabbitmq #amqp #весна-кролик #spring-amqp
Вопрос:
Я вызываю:
GetResponse response = channel.basicGet("some.queue", false); // no auto-ack
....
channel.basicAck(deliveryTag, ...);
Однако, когда я вызываю basicGet
, сообщения в очереди остаются в «Готовности», а не в «Неподтвержденном». Я хочу, чтобы они были в неподтвержденном состоянии, чтобы я мог либо basic.ack
их (таким образом, отбрасывая их из очереди), либо basic.nack
их
Ответ №1:
Я делаю следующее, чтобы имитировать задержку подтверждения:
Во время потребления
- Получить (использовать) сообщение из начальной очереди.
- Создайте очередь «PendingAck_123456».
123456 — это уникальный идентификатор сообщения.
Задайте следующие свойства- x-сообщение-ttl (для запроса после тайм-аута)
- x-истекает (чтобы убедиться, что временная очередь будет удалена)
- x-dead-letter-exchange и x-deal-letter-routing-ключ для запроса в начальную очередь по истечении срока действия TTL.
- Опубликуйте ожидающее подтверждения сообщение в этой очереди «PendingAck_123456»
- Подтвердите сообщение, чтобы удалить его из начальной очереди
Во время подтверждения
- Вычислить имя очереди из идентификатора сообщения и получить из очереди «PendingAck_123456»
- Подтвердите это (нет необходимости вызывать
.getBody()
).
Это удалит его из этой очереди ожидания, не позволяя TTL запрашивать его
Примечания
- Очередь только для 1 сообщения.. Это проблема, если таких очередей много?
- На стороне ввода очереди будет отправлено сообщение с запросом.. не на выходе очереди (как это было бы при реальном подтверждении).. Это влияет на порядок сообщений.
- Приложение копирует сообщение в очередь ожидания.. Это дополнительный шаг, который может повлиять на общую производительность.
- Чтобы имитировать Nack / Reject, вы можете скопировать сообщение в начальную очередь и подтвердить его из очереди PendingAck. По умолчанию TTL сделает это (позже).
Ответ №2:
При выполнении ack
сразу после get
этого все работает нормально. Однако в моем случае они были разделены по просьбе. И шаблон spring закрывает канал и соединение при каждом выполнении. Итак, есть три варианта:
- поддерживайте один канал и соединение открытыми в течение всего срока службы приложения
- создайте какую-то область диалога (или, в худшем случае, используйте сеанс), чтобы сохранить один и тот же канал и повторно использовать его.
- используйте один канал для каждого запроса, немедленно подтверждайте получение и сохраняйте сообщения в памяти.
В первых двух случаях вы не можете сделать это с помощью spring RabbitTemplate