RabbitMq确认机制


一、RabbitMQ特性

    持久化:消息持久化到磁盘,需要满足三个条件:
  • 投递模式选项设置为2(持久)
  • 发送到持久化的交换器
  • 到达持久化的队列

    事物:RabbitMQ支持事物,但是事物是同步的,性能太差。RabbitMQ中与事务机制有关的方法有三个:txSelect(), txCommit()以及txRollback(), txSelect用于将当前channel设置成transaction模式,txCommit用于提交事务,txRollback用于回滚事务,在通过txSelect开启事务之后,我们便可以发布消息给broker代理服务器了,如果txCommit提交成功了,则消息一定到达了broker了,如果在txCommit执行之前broker异常崩溃或者由于其他原因抛出异常,这个时候我们便可以捕获异常通过txRollback回滚事务了。
try {
    channel.txSelect();
    channel.basicPublish(exchange, routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN, msg.getBytes());
    channel.txCommit();
} catch (Exception e) {
    e.printStackTrace();
    channel.txRollback();
}


    确认机制(Comfirm):分消费端comfirm和生产端comfirm。事物和确认机制都是为了保证消息不丢失。确认机制是异步的,比事物性能高。
  • basic.ack:确认收到消息
  • basic.nack:拒绝消息,支持requeue,支持批量nack(reject的加强版)
  • basic.reject:拒绝消息,支持requeue,不支持批量

    broker是轮流给Consumer发送消息的,如果requeue的消息broker就会轮流发到下一个Consumer。如果没有Ack也没有NoAck,broker会挂起这个消息(至到消费该消息的Consumer连接断掉才会requeue该消息),没有NoAck的Consumer还是会收到消息。

二、Consumer Comfirm

  订阅消息时将autoAck设置为true的话,那么你处理完消息之后就无须再发送确认消息回服务器。这样就能极大的加快消费者消费的速度。否则需要代码手动ack。
final Consumer consumer = new DefaultConsumer(channel) {
        @Override
        public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body)
                throws IOException {
            String message = new String(body, "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
            this.getChannel().basicAck(envelope.getDeliveryTag(), false);
        }
};
channel.basicConsume(QUEUE_NAME, false, consumer); //第二个参数autoAck为false


三、Producer Comfirm

    生产者将信道设置成confirm模式,一旦信道进入confirm模式,所有在该信道上面发布的消息都会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,broker就会发送一个确认给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了,如果消息和队列是可持久化的,那么确认消息会将消息写入磁盘之后发出,broker回传给生产者的确认消息中deliver-tag域包含了确认消息的序列号,此外broker也可以设置basic.ack的multiple域,表示到这个序列号之前的所有消息都已经得到了处理。

    confirm模式最大的好处在于他是异步的,一旦发布一条消息,生产者应用程序就可以在等信道返回确认的同时继续发送下一条消息,当消息最终得到确认之后,生产者应用便可以通过回调方法来处理该确认消息,如果RabbitMQ因为自身内部错误导致消息丢失,就会发送一条nack消息,生产者应用程序同样可以在回调方法中处理该nack消息。

    在channel 被设置成 confirm 模式之后,所有被 publish 的后续消息都将被 confirm(即 ack) 或者被nack一次。但是没有对消息被 confirm 的快慢做任何保证,并且同一条消息不会既被 confirm又被nack 。
  
    已经在transaction事务模式的channel是不能再设置成confirm模式的,即这两种模式是不能共存的。
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.confirmSelect();                              //Producer端开启comfirm模式
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        String message = "Hello World!";
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        System.out.println(" [x] Sent '" + message + "'");
        channel.close();
        connection.close();

猜你喜欢

转载自ncs123.iteye.com/blog/2394006
今日推荐