2017-02-03 3 views
0

Вопрос: После фиксированного количества повторных попыток я хочу отправить сообщение в очередь ошибок и уничтожить его из исходной очереди. Я хочу найти общее решение, потому что я обрабатываю множество разных сообщений, и в зависимости от того, какое из них они делают, я хочу действовать по-другому. Как установить RecoveryCallback так, чтобы Spring запускал его после maxRetries?Spring RabbitTemplate setRetryTemplate & setRecoveryCallback проигнорирован

То, что я в настоящее время делают
Я пытаюсь установить RetryTemplate и RecoveryCallback. Когда я запускаю приложение и публикую сообщение в очереди test, я ожидаю, что обработка в EListener#receive завершится с ошибкой 3 раза, а затем запустит мой сконфигурированный RecoveryCallback, который затем направит сообщение на основе контекста в определенную очередь ошибок.

Что на самом деле происходит Что на самом деле происходит в том, что Spring загрузка инициализирует RabbitAdmin объекта с его собственной RabbitTemplate и поэтому не использует мой сконфигурированный RabbitTemplate боба.

Я следующую структуру каталогов:

rabbit 
    |___ EListener.java 
    |___ Rabbit.java 
test 
    |___ Test.java 

Я следующий код в Rabbit.java

@Configuration 
public class Rabbit { 

    @Autowired 
    ConnectionFactory connectionFactory; 

    @Bean 
    public RabbitTemplate rabbitTemplate() { 
     RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); 
     rabbitTemplate.setRetryTemplate(createRetryTemplate()); 
     rabbitTemplate.setRecoveryCallback(createRecoveryCallback()); 
     return rabbitTemplate; 
    } 

    createRecoveryCallback() // Omitted for brevity 
    createRetryTemplate() // Omitted for brevity 
} 

The EListener.java файл содержит:

@Component 
public class EListener { 

    @Autowired 
    RabbitTemplate rabbitTemplate; 

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "test", durable = "true"), exchange = @Exchange(value = "test", type = ExchangeTypes.TOPIC, durable = "true", autoDelete = "true"), key = "test")) 
    public void receive(Message m) throws Exception { 
     System.out.println(m); 
     throw new Exception(); 
    } 
} 

Test.java содержит:

@SpringBootApplication 
@ComponentScan("rabbit") 
public class Test { 

    public static void main(String[] args) { 
     new SpringApplicationBuilder(Test.class).application().run(args); 
    } 
} 

ответ

0

Добавление RetryTemplate к RabbitTemplate, чтобы повторить попытку издательских сообщений.

Чтобы добавить повтор на стороне потребителя, вы должны добавить перехватчик повтора к слушателю container's advice chain.

С тех пор как вы используете @RabbitListener, цепочка консультаций идет по адресу listener container factory @Bean, что означает, что вам придется объявить один самостоятельно, вместо того чтобы полагаться на стандартную версию, созданную при загрузке.

Повторите попытку без повторного использования в памяти; statefull повторяет запрос сообщения; для этого требуется свойство messageId (или какой-либо другой механизм для однозначной идентификации сообщений).

+0

Можно ли просто заменить «RejectAndDontRequeueRecoverer», который в настоящее время используется как восстановитель по умолчанию? – dparted

+0

К сожалению, нет; восстановитель жестко подключен к [перехватчику повторных попыток загрузки] (https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework /boot/autoconfigure/amqp/SimpleRabbitListenerContainerFactoryConfigurer.java#L104). Вы можете подключить свой собственный компонент (https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ amqp/RabbitAnnotationDrivenConfiguration.java # L62) используйте конфигуратор загрузки, а затем перезапишите 'adviceChain' своим собственным перехватчиком. –

+0

Тогда я сделаю это. Было бы здорово иметь это в первую очередь. Спасибо за помощь. – dparted

Смежные вопросы