繁体   English   中英

如何异步发送消息以排队它们而不等待使用java中的rabbitmq在spring amqp中回复每条消息?

[英]How to send messages asynchronously to queue them up without waiting for reply of each message in spring amqp using rabbitmq in java?

我正在尝试使用spring amqp使用rabbitmq,下面是我的配置。

<rabbit:connection-factory id="rabbitConnectionFactory"
    port="${rabbitmq.port}" host="${rabbitmq.host}" />

<rabbit:admin connection-factory="rabbitConnectionFactory" />

<rabbit:queue name="${rabbitmq.import.queue}" />

<rabbit:template id="importAmqpTemplate"
    connection-factory="rabbitConnectionFactory" queue="${rabbitmq.import.queue}"  routing-key="${rabbitmq.import.queue}"/>

<rabbit:listener-container
    connection-factory="rabbitConnectionFactory" concurrency="5">
    <rabbit:listener queues="${rabbitmq.import.queue}" ref="importMessageListener"  method="onMessage" />
</rabbit:listener-container>

这是一个简单的Message Listener类,

public class ImportMessageListener {

    @Override
    public void onMessage(Message message) {
        System.out.println("consumer output: " + message);
        return message;
    }

}

这是生产者(春季批次的itemWriter),

public class ImportItemWriter<T> implements ItemWriter<T> {

    private AmqpTemplate template;

    public AmqpTemplate getTemplate() {
        return template;
    }

    public void setTemplate(AmqpTemplate template) {
        this.template = template;
    }

    public void write(List<? extends T> items) throws Exception {
        for (T item : items) {
            Object reply = template.convertSendAndReceive(item.toString());
            System.out.println("producer output: " + reply);
        }
    }

}

当我运行我的春季批处理作业时,每个消息都是逐个发送和处理的,我在响应之下

consumer output: 1
producer output: 1

consumer output: 2
producer output: 2

consumer output: 3
producer output: 3

consumer output: 4
producer output: 4


consumer output: 5
producer output: 5

它应该发送5条消息并将它们排队,5个消费者线程(并发= 5)应该同时处理它们并且应该在它完成后立即响应

So below should be the outout

consumer output: 1
consumer output: 2
consumer output: 3
consumer output: 4
consumer output: 5

producer output: 1
producer output: 2
producer output: 3
producer output: 4
producer output: 5

我不希望生产者等待第一条消息的回复来排队第二条消息。

我尝试使用convertAndSend使其成为异步(不等待回复)但是如何在我的itemWriter中获得回复消息,就像我可以使用convertSendAndReceive一样?

如果我将模板配置更改为

<rabbit:template id="importAmqpTemplate"
        connection-factory="rabbitConnectionFactory" queue="${rabbitmq.import.queue}"
        routing-key="${rabbitmq.import.queue}" reply-queue="${rabbitmq.import.reply.queue}">
        <rabbit:reply-listener/>
    </rabbit:template>

如果我使用template.convertAndSend(item.toString()); 那怎么才能收到回复信息?

我无法将自己的消息处理程序附加到此侦听器,以便按照我们在消费者端附加的方式获取回复消息。 对于回复,它采用默认的RabbitmqTemplate处理程序。

首先让我解释一下发生了什么

您使用同步 sendAndReceive操作。 在您的消息发送之前,它将使用TemporaryReplyQueue丰富,并且发送方(生产者)线程正在阻止等待来自该replyQueue的回复。 这就是为什么所有消息都是串行处理的原因。

要继续,我们需要知道在单向ItemWriter生成器中使用该操作的原因。

也许RabbitTemplate#convertAndSend对你来说已经足够了?

UPDATE

也许你只是需要RabbitTemplate.ReturnCallback一起与convertAndSend来确定,如果你的消息已被传递或没有?

更新2

另一个想法是实现您使用TaskExecutor并行发送和接收的要求。 有了这个,您不需要等待依赖第一条消息发送第二条消息:

final List<Object> replies = new ArrayList<Object>();
ExecutorService executor = Executors.newCachedThreadPool();
for (T item : items) {
     executor.execute(new Runnable() {

         public void run() {
            Object reply = template.convertSendAndReceive(item.toString());
            System.out.println("producer output: " + reply);
            replies.add(reply);
         }
     });
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);

之后,您可以对当前items所有replies执行某些操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM