RabbitMQの+炉、メッセージに通過した後にACKを送信しますか?

Gelunox:

私はプロジェクト炉は私のユースケースのための実行可能な選択肢であるかどうかを把握しようとしています。

私は私がしたい、自分のアプリケーションで高い一貫性を必要とします:

  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

原子炉-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>終了状態を。

私は私がここで使用することができ、何かが欠けてるように私は感じるので、原子炉の私の知識は、その広範囲ではありません。原子炉できちんとこれを実行することが可能であるか、私はそれを忘れなければなりませんか?


脚注:私は使用していますvar、私はJavaの11でだから、物事が実行される順序を定量化する方法として、print文。

pmackowski:

私は内部の送信方法を確認することが可能であるとは思いません。代わりに、あなたは試すことができます:

receiver.consumeManualAck("queue.A")
        .flatMap(ad -> {
           Mono<OutboundMessage> outboundMessageMono =
                Mono.just(new OutboundMessage("", "queue.B", ad.getBody()));
           return sender.send(outboundMessageMono)
                        .doFinally(signalType -> {
                            if (signalType == SignalType.ON_COMPLETE) {
                               ad.ack();
                            } else {
                               ad.nack(false);
                           }
                         });
         });

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=219847&siteId=1