【问题标题】:MessageListener.onMessage is getting called continuously on RabbitMQ with Spring Boot使用 Spring Boot 在 RabbitMQ 上不断调用 MessageListener.onMessage
【发布时间】:2020-05-10 12:21:52
【问题描述】:

我有一个线程睡眠的 MessageListener.onMessage。我正在模拟 onMessage 的实际处理时间 方法将由上述线程睡眠。但是我注意到的是,剩余的消息会被连续多次调用,直到它们被 onMessage 方法处理。我认为这是一种低效率。

队列中的实际消息数:1000

点击次数的输出

onMessage<<15656
onMessage<<15657
onMessage<<15658
onMessage<<15659
onMessage<<15660
onMessage<<15661
onMessage<<15662
onMessage<<15663

代码块

@Service
class ThreadPooledMessageListener implements MessageListener {
@Autowired
TaskExecutor threadPoolTaskExecutor;

AtomicInteger processedCount = new AtomicInteger();

@Override
public void onMessage(Message message) {
    System.out.println("onMessage<<" + processedCount.incrementAndGet());
    threadPoolTaskExecutor.execute(new MessageProcessor(message));

}
}

class MessageProcessor implements Runnable {
Message processingMessage;

public MessageProcessor(Message message) {
    this.processingMessage = message;
}

@Override
public void run() {
    System.out.println("================================"+ Thread.currentThread().getName());
    System.out.println(processingMessage);
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("================================");
}
}

对此有什么可能的解决方法。


正如@Gary Russell 指出的那样;问题是我在我的代码中使用了非弹簧托管容器 SimpleMessageListenerContainer。使用 spring 托管 bean 修复它并在那里定义并发。按预期工作。 固定代码段

    @Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer() {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
    container.setQueues(queue);
    container.setMessageListener(threadPooledMessageListener);
    container.setConcurrentConsumers(4);
    container.start();
    return container;
}

【问题讨论】:

    标签: spring-boot rabbitmq spring-amqp


    【解决方案1】:

    &gt;I see this as an inefficiency.

    不清楚你的意思。由于您将消息的处理移交给另一个线程,因此侦听器立即退出,当然,下一条消息将被传递。

    如果发生故障,这将面临消息丢失的风险。

    如果你想实现并发;最好设置容器concurrentConsumers 属性,不要在监听器中进行自己的线程管理。容器将为您管理消费者。

    【讨论】:

    • 我担心的是,如果生产者正在做 for (int i = 0; i
    • 为什么只有 100 条消息,监听器会被调用 6 万次?那不会发生。
    • 我已经尝试过了,它的工作原理是这样的,可能是我错过了一些东西。你可以在 github 上看到它。 github.com/DonSrinath/spring-amqp-rabbit-docker/tree/master/…
    • 你为什么要在Consumer.init()创建一个非spring管理的容器?那是完全错误的。 Spring 需要管理容器。我真的不想再浪费时间查看该代码了。你真的需要看concurrentConsumers才能实现并发。
    • 感谢您的浏览。是的,使用非弹簧托管容器是问题所在,将 concurrentConsumers 与弹簧托管容器一起使用,它按预期工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    • 1970-01-01
    相关资源
    最近更新 更多