rabbitmq消费端的nack和重回队列的总结

消费者

package com.mq.rabbit.ack;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * @Author Mqs
 * @Date 2018/10/28 22:14
 * @Desc
 */
public class Consumer {
    public static void main(String[] args)throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setVirtualHost("/");
        factory.setPort(AMQP.PROTOCOL.PORT);
        factory.setHost("192.168.200.130");
        factory.setUsername("rollen");
        factory.setPassword("root");

        Connection connection = factory.newConnection();

        Channel channel = connection.createChannel();

        String routingKey = "ack_key";
        String exchangeName = "ack_exchange";
        String queueName = "ack_queue";
        String exchangeType = "topic";

        channel.exchangeDeclare(exchangeName, exchangeType, true, false, null);
        channel.queueDeclare(queueName, true, false, false, null);

        channel.queueBind(queueName, exchangeName, routingKey);

        // 由于消费段的ack是手工签收,所以 autoAck = false
        channel.basicConsume(queueName, false, new MyConsumer(channel));
    }
}

 

package com.mq.rabbit.ack;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import org.omg.CORBA.TRANSACTION_MODE;

import java.io.IOException;

/**
 * @Author Mqs
 * @Date 2018/10/28 22:45
 * @Desc
 */
public class MyConsumer extends DefaultConsumer {

    private Channel channel;
    /**
     * Constructs a new instance and records its association to the passed-in channel.
     *
     * @param channel the channel to which this consumer is attached
     */
    public MyConsumer(Channel channel) {
        super(channel);
        this.channel = channel;
    }

    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        super.handleDelivery(consumerTag, envelope, properties, body);
        System.out.println("==properties: " + properties.getHeaders().get("pc"));
        Integer num = (Integer)properties.getHeaders().get("num");

        System.out.println("==body: " + new String(body));

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /**
         * 第1条数据的num是0,会进到nack
         * 然后这条消息会从新回到队列
         * 回到队列的尾部,被重新消费
         */
        if (num == 0){
            // TODO 最后一个参数 requeue 设置为true 会把消费失败的消息从新添加到队列的尾端,设置为false不会重新回到队列
            channel.basicNack(envelope.getDeliveryTag(), false, true);
            System.out.println("==============第:" + num + "条消息------没有被消费");
        }else {
            System.out.println("==============第:" + num + "条消息-------被消费");
            channel.basicAck(envelope.getDeliveryTag(), false);
        }




    }
}

生产者

package com.mq.rabbit.ack;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author Mqs
 * @Date 2018/10/28 22:14
 * @Desc
 */
public class Producer {
    public static void main(String[] args)throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setVirtualHost("/");
        factory.setPort(AMQP.PROTOCOL.PORT);
        factory.setHost("192.168.200.130");
        factory.setUsername("rollen");
        factory.setPassword("root");

        Connection connection = factory.newConnection();

        Channel channel = connection.createChannel();

        String routingKey = "ack_key";
        String exchangeName = "ack_exchange";

        String msg = "this is a message provide by ack producer";

        for (int i = 0; i < 5; i++){
            Map<String, Object> map = new HashMap<>();
            map.put("pc", "个人笔记本电脑");
            map.put("num", i);
            AMQP.BasicProperties properties = new AMQP.BasicProperties().builder()
                    .deliveryMode(2)
                    .contentEncoding("UTF-8")
                    .headers(map).build();

            channel.basicPublish(exchangeName, routingKey, true, properties, msg.getBytes());
            System.out.println("生产者发送第:" + i + " 条消息");
        }

    }
}

结果演示

==properties: 个人笔记本电脑
==body: this is a message provide by ack producer
==============第:0条消息------没有被消费
==properties: 个人笔记本电脑
==body: this is a message provide by ack producer
==============第:1条消息-------被消费
==properties: 个人笔记本电脑
==body: this is a message provide by ack producer
==============第:2条消息-------被消费
==properties: 个人笔记本电脑
==body: this is a message provide by ack producer
==============第:3条消息-------被消费
==properties: 个人笔记本电脑
==body: this is a message provide by ack producer
==============第:4条消息-------被消费
==properties: 个人笔记本电脑
==body: this is a message provide by ack producer
==============第:0条消息------没有被消费
==properties: 个人笔记本电脑
==body: this is a message provide by ack producer
==============第:0条消息------没有被消费
==properties: 个人笔记本电脑
==body: this is a message provide by ack producer
==============第:0条消息------没有被消费
==properties: 个人笔记本电脑
==body: this is a message provide by ack producer

图解

第0条消息从新回到对列,但是就是一直无法被消费

RabbitMQ 中,消费者可以通过创建一个消息监听器来监听指定的队列,并在接收到消息后进行消息确认(ACK)。 下面是一个示例代码,展示了如何使用 RabbitMQ Java 客户端库来实现消息监听和消息确认: ```java import com.rabbitmq.client.*; public class Consumer { private final static String QUEUE_NAME = "myQueue"; public static void main(String[] argv) throws Exception { // 创建连接工厂,并设置 RabbitMQ 服务器的连接信息 ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setUsername("your_username"); factory.setPassword("your_password"); // 创建连接 Connection connection = factory.newConnection(); // 创建消息信道 Channel channel = connection.createChannel(); // 声明队列 channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 创建消费者并设置消息处理逻辑 DefaultConsumer 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("Received message: " + message); // 处理消息逻辑 // 手动发送消息确认 channel.basicAck(envelope.getDeliveryTag(), false); } }; // 设置消息确认模式为手动确认 channel.basicConsume(QUEUE_NAME, false, consumer); // 等待消息 while (true) { Thread.sleep(1000); } } } ``` 在上述代码中,首先创建了一个连接工厂,并设置 RabbitMQ 服务器的连接信息。然后创建连接和消息信道,声明了要消费队列。 接着创建了一个继承自 DefaultConsumer消费者对象,并重写了 handleDelivery 方法来处理接收到的消息。在处理消息的逻辑之后,使用 `channel.basicAck(envelope.getDeliveryTag(), false)` 手动发送消息确认。 最后,通过调用 `channel.basicConsume(QUEUE_NAME, false, consumer)` 来设置消费者的消息确认模式为手动确认,并开始等待消息的到来。 请根据你的实际需求进行相应的修改和优化。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞流2023

小主,破费了,回头请你喝咖啡!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值