RabbitMQ之常用API

一.消費者確認機制

一.消費者確認

消費者確認或者說消費者應答指的是RabbitMQ需要確認消息到底有沒有被收到。

RabbitMQ中的兩種確認方式:
  • 自動確認方式:RabbitMQ成功將消息發出(即將消息成功寫入TCP Socket)中立即認爲本次投遞已經被正確處理,不管消費者端是否成功處理本次投遞
  • 手動處理方式:消費者收到消息後,手動調用basic.ack/basic.nack/basic.reject後,RabbitMQ收到這些消息後,才認爲本次投遞成功
1. 自動應答
boolean autoAck = true;
channel.basicConsume(QUEUE_NAME, autoAck, consumer);
2. 手動應答
boolean autoAck = false;
channel.basicConsume(QUEUE_NAME, autoAck, consumer);

二.消息消費

(1) 單一消費

channel.basicAck(envelope.getDeliveryTag(), false)

(2) 批量消費

channel.basicAck(envelope.getDeliveryTag(), true)

  • deliveryTag:該消息的index
  • multiple:是否批量.true:將一次性ack所有小於deliveryTag的消息。

(3) basicNack

channel.basicNack(delivery.getEnvelope().getDeliveryTag(), false, true);

  • deliveryTag:該消息的index
  • multiple:是否批量.true:將一次性拒絕所有小於deliveryTag的消息。
  • requeue:被拒絕的是否重新入隊列

(4) 拒絕單條消息 basicReject

void basicReject(long deliveryTag, boolean requeue) throws IOException;

  • deliveryTag:發佈的每一條消息都會獲得一個唯一的deliveryTag,它在channel範圍內是唯一的
  • requeue:表示如何處理這條消息,爲true表示重新放入RabbitMQ的發送隊列中,爲false表示通知RabbitMQ銷燬該消息

channel.basicNack 與 channel.basicReject 的區別在於basicNack可以拒絕多條消息,而basicReject一次只能拒絕一條消息

(5) 拒絕多條消息 basicReject

void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException;

  • deliveryTag:發佈的每一條消息都會獲得一個唯一的deliveryTag,它在channel範圍內是唯一的

  • multiple:批量確認標誌,爲true表示包含當前消息在內的所有比該消息的deliveryTag值小的消息都被拒絕, 除了已經被應答的消息。爲false則表示只拒絕本條消息

  • requeue:表示如何處理這條消息,爲true表示重新放入RabbitMQ的發送隊列中,爲false表示通知RabbitMQ銷燬該消息

需要注意:如果隊列中只有一個消費者的時候,需要確認不會因爲拒絕消息並重新放入消息隊列中而導致在同一個消費者身上發生死循環。

(6) 重新投遞 basicRecover

Basic.RecoverOk basicRecover(boolean requeue);

重新投遞並沒有所謂的像basicReject中的basicReject的deliveryTag參數,所以重新投遞好像是將消費者還沒有處理的所有的消息都重新放入到隊列中,而不是將某一條消息放入到隊列中,與basicReject不同的是,重新投遞可以指定投遞的消息是否允許當前消費者消費。

(7) 是否重複投遞

envelope.isRedeliver()

  • true :重複投遞
  • false: 首次投遞

三.隊列Queue

(1) 定義i隊列 queueDeclare

channel.queueDeclare(QUEUE_NAME, false, false, false, null);

  • durable:true、false true:在服務器重啓時,能夠存活
  • exclusive :是否爲當前連接的專用隊列,在連接斷開後,會自動刪除該隊列,生產環境中應該很少用到吧。
  • autodelete:當沒有任何消費者使用時,自動刪除該隊列。this means that the queue will be deleted when there are no more processes consuming messages from it.

四.通道Channel相關

(1) 綁定隊列

Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
Map<String, Object> arguments) throws IOException;

channel.queueDeclare("Queue", true, false, false, null);

(2) 刪除隊列

Queue.DeleteOk queueDelete(String queue) throws IOException;

(3) 刪除隊列

Queue.DeleteOk queueDelete(String queue, boolean ifUnused, boolean ifEmpty) throws IOException;

  • ifUnused 如果爲true,則只有在通道沒有在使用才被刪除。
  • ifEmpty 如果爲true,則只有在通道爲空才被刪除。

(5) 清空隊列

Queue.PurgeOk queuePurge(String queue) throws IOException;

(6) 發佈消息

void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;

  • exchange 交換機,可爲null
  • routingKey 路由密鑰,如隊列名稱
  • props 屬性 ,可爲null
  • body 消息主體

如下:

channel.queueDeclare(queueName, true, false, false, null);

(7) 清空隊列

Queue.PurgeOk queuePurge(String queue) throws IOException;

(14) basicCancel

同時對於Consumer來說重寫handleDelivery方法也是十分方便的。更復雜的Consumer會重寫(override)更多的方法,比如handleShutdownSignal當channels和connections close的時候會調用,handleConsumeOk在其他callback方法之前調用,返回consumer tags.

Consumer同樣可以override handleCancelOk和handleCancel方法,這樣在顯示的或者隱式的取消的時候調用。

你可以通過Channel.basicCancel方法顯示的cancel一個指定的Consumer

channel.basicCancel(consumerTag);

(譯者注:這句代碼首先觸發handleConsumerOk,之後觸發handleDelivery方法,最後觸發handleCancelOk方法。)

單個Consumer在Connection上都分配單個的線程來調用這些callback的方法,也就是說Consumer這裏安全的調用阻塞式的方法,比如queueDeclare, txCommit, basicCancel或者basicPublish。

二.發送消息確認
(1) 單次確認

waitForConfirms

 Channel channel = connection.createChannel();
        channel.queueDeclare(queueName, true, false, false, null);
        //將當前信道設置成了confirm模式
        channel.confirmSelect();

        channel.basicPublish("", queueName, null, message.getBytes());

        try {
            //等待broker服務端返回ack或者nack消息
            boolean success = channel.waitForConfirms();
            Log.d(TAG, "隊列-" + queueName + "-發送消息:" + message+"  狀態:"+success);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

可以看到上面生產者通過Confirm.Select將當前Channel信道設置成confirm模式,broker代理服務器收到之後回傳Confirm.Select-Ok同一將當前Channel設置成confirm模式,此外看到返回5條Basic.Ack消息;

(2) 批量確認

addConfirmListener

//開啓確認模式
channel.confirmSelect();
channel.addConfirmListener(new ConfirmListener() {
            //消息失敗處理
            @Override
            public void handleNack(long deliveryTag, boolean multiple) throws IOException {
                //deliveryTag;唯一消息標籤
                //multiple:是否批量
                System.err.println("-------no ack!-----------");
            }
            //消息成功處理
            @Override
            public void handleAck(long deliveryTag, boolean multiple) throws IOException {
                System.err.println("-------ack!-----------");
            }
        });
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章