RabbitMQ + Reactor,传递消息后发送ACK?

时间:2019-01-17 07:56:58

标签: java rabbitmq project-reactor reactor-rabbitmq

我正在尝试确定Project-Reactor是否适合我的用例。

我需要在我的应用程序中保持高度一致性,

  1. 从RabbitMQ接收消息
  2. 进行一些操作/转换
  3. 将消息放在(不同的)RabbitMQ队列上
  4. 发送原始消息的ACK

使用普通的RabbitMQ Java库,其外观大致如下:

var connectionFactory = new ConnectionFactory();
var connection = connectionFactory.newConnection();
var channel = connection.createChannel();
channel.txSelect();
channel.queueDeclare("queue.A", true, false, false, null);
channel.queueDeclare("queue.B", true, false, false, null);

channel.basicConsume("queue.A", false, (tag, delivery) ->
{
    String data = new String(delivery.getBody(), StandardCharsets.UTF_8);
    System.out.println("Received: " + data);
    channel.basicPublish("", "queue.B", null, data.getBytes(StandardCharsets.UTF_8));
    channel.txCommit();
    System.out.println("Sending ACK");
    channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
    channel.txCommit();

}, tag -> System.err.println("Tag " + tag + " failed"));

这很好地打印

Received: DATA
Sending ACK

使用Reactor-RabbitMQ我提出了以下建议:

var options = new ReceiverOptions();
var receiver = RabbitFlux.createReceiver(options);
var sender = RabbitFlux.createSender();
sender.declare(QueueSpecification.queue("queue.A")).block();
sender.declare(QueueSpecification.queue("queue.B")).block();
sender
    .send(receiver.consumeManualAck("queue.A")
        .doOnError(ex -> ex.printStackTrace())
        .doOnEach(s ->
        {
            s.get().ack();
            print("ACK");
        })
        .map(ad ->
        {
            print("MAP");
            return new OutboundMessage("", "queue.B", ad.getBody());
        }))
    .doOnEach(v ->
    {
        print("SUB");
    })
    .subscribe();

但是,此打印

ACK
MAP

显然,这不是正确的顺序,因为我在doOnEach之前执行map。但是在我将AcknowledgableDelivery映射到发件人的OutboundMessage之后,它不再可用。

请注意,从未打印过SUB。可能是因为send订阅是连续的,并且从未达到Mono<Void>终止状态。

我对Reactor的了解并不广泛,所以我觉得我缺少在这里可以使用的东西。是否可以使用Reactor巧妙地做到这一点,还是我应该忘记它?


脚注:我使用var是因为我在Java 11中,所以使用print语句来量化执行顺序。 < / em>

1 个答案:

答案 0 :(得分:0)

我认为不可能在send方法内部进行确认。相反,您可以尝试:

library(tidyverse)

data %>% 
  unnest(mecanicas) %>% 
  select(name, title)