Spring AMQP: как избежать ручного объявления многих очередей?

Создав базовую настройку spring-amqp, я вижу, что для каждого типа сообщения, которое я хочу отправить (с использованием сообщений POJO), мне нужно объявить очередь в конфигурации spring.

Итак, для каждой пары из них:

amqpTemplate.convertAndSend("queue1", new MessageType1(...));

@RabbitListener(queues = "queue1")
public void handleMessage(MessageType1 msg) {...}

Мне нужна запись в конфигурации spring следующим образом:

<rabbit:queue name="queue1"/>

Мне это кажется излишним. Если я думаю об очередях, таких как URL-адреса HTTP, то достаточно объявить контроллер с @RequestMapping("/some-url"), нет необходимости также объявлять /some-url в другом месте конфигурации.

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

Я вижу два способа избежать этого:

  1. Автоматическое объявление очередей для каждой аннотированной конечной точки прослушивателя. т. е. если есть аннотированная конечная точка прослушивателя @RabbitListener(queues = "hello"), то можно сделать вывод, что должна быть объявлена ​​очередь hello. Я думал, что это может быть уже так, но когда я удалил очередь из конфигурации контекста, я получил следующую ошибку:

    WARN  BlockingQueueConsumer - Failed to declare queue:hello
    WARN  BlockingQueueConsumer - Queue declaration failed; retries left=2
    org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$DeclarationException: Failed to declare queue(s):[hello]
        at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.attemptPassiveDeclarations(BlockingQueueConsumer.java:479)
        at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.start(BlockingQueueConsumer.java:400)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1022)
    
  2. Использование разных POJO сообщений в одной очереди. Таким образом, отправка MessageType1 и MessageType2 на queue1, каждая из которых достигает другой конечной точки, в зависимости от типа полезной нагрузки. По сути, это создает своего рода единую «очередь приложений», аналогичную схеме базы данных:

    @RabbitListener(queues = "queue1")
    public void handleMessage1(MessageType1 msg) {...}
    
    @RabbitListener(queues = "queue1")
    public void handleMessage2(MessageType2 msg) {...}
    

    Попытка этого подхода привела к ошибке.

Возможно ли что-либо из вышеперечисленного в настоящее время с помощью spring-amqp (1.4.0), и если да, то как?


person Amir Abiri    schedule 24.11.2014    source источник
comment
Вы изучали удаленное взаимодействие через AMQP? Он использует механизм, который вы подразумеваете в (2). Я не знаю контекста, но это может сработать для вас.   -  person David    schedule 24.11.2014


Ответы (1)


В настоящее время невозможно автоматически объявлять @RabbitListener очереди, но это звучит разумно. Конечно, одного объявления очереди может быть недостаточно; в то время как он будет привязан к обмену по умолчанию "" с именем очереди в качестве ключа маршрутизации, любая более сложная привязка в любом случае потребует дополнительной настройки.

Использование имени очереди в качестве ключа маршрутизации с обменом по умолчанию не считается лучшей практикой, поскольку оно связывает производителя и потребителя. Но я понимаю, что иногда он используется, поэтому введите выпуск новой функции JIRA, и мы рассмотрю это.

Кстати, вы также можете использовать @Bean вместе с слушателями, чтобы избежать конфигурации XML.

Ваш второй запрос может быть реализован делегирующим прослушивателем сообщений:

@RabbitListener(queues = "queue1")
public void handleMessage(Object o) {
    if (o instanceof Type1) {
        delegate.type1((Type1) o);
    }
    else if (o instanceof Type2) {
        delegate.type2((Type2) o);
    } 
}

Я думал о предоставлении такого слушателя (в более общем виде). Опять же, пожалуйста, откройте новую проблему функции.

ИЗМЕНИТЬ

Обе эти функции теперь доступны в версии 1.5. @QueueBinding и Уровень класса @RabbitListener.

person Gary Russell    schedule 24.11.2014
comment
Я начинаю понимать, что мне следует думать об очередях больше как о таблицах базы данных, чем об URL-адресах REST. Если мы подумаем о них таким образом, то имеет смысл где-то существовать файл схемы DDL. Однако, как говорится, с Hibernate, использующим аннотации, мы не стали бы писать такой DDL, а скорее выводили бы его из наших аннотаций POJO. Возможно, здесь можно применить аналогичный подход, когда аннотации прослушивателя могут предоставить подробную информацию об очереди. В любом случае я перенесу обсуждение в JIRA. - person Amir Abiri; 24.11.2014
comment
Теперь возможно автоматическое объявление, начиная с Spring AMQP 1.5.0, который в настоящее время находится в M1. См. документы. .spring.io/spring-amqp/docs/1.5.0.M1/reference/html/ - person David; 18.06.2015