RabbitMQ的消息应答机制和轮询策略

消息应答

消息应答就是:消费者在接收到消息并且处理该消息之后,告诉 rabbitmq 它已经处理了,rabbitmq 可以把该消息删除了。这个默认是公平分发。

消息自动应答

如果配置的是自动应答,那么消息发送后立即被认为已经传送成功,如果程序这时候突然宕机,那么消息直接丢失,这是很不安全的。所以这种模式仅适用在消费者可以高效并以某种速率能够处理这些消息的情况下使用

消息手动应答介绍

消息应答方法

A.Channel.basicAck(用于肯定确认) RabbitMQ 已知道该消息并且成功的处理消息,可以将其丢弃了
B.Channel.basicNack(用于否定确认)
C.Channel.basicReject(用于否定确认)Channel.basicNack 相比少一个参数 不处理该消息了直接拒绝,可以将其丢弃了
消息应答里的Multiple(批量应答)参数的解释

在这里插入图片描述
在这里插入图片描述

消息自动重新入队

当消费者二号还没接收到信息A就宕机时,信息A会去消费者一号重新排队,然后被消费者一号接受

消费手动应答代码

睡眠工具类

public class SleepUtils {
    public static void sleep(int second) {
        try {
            Thread.sleep(1000 * second);
        } catch (InterruptedException _ignored) {
            Thread.currentThread().interrupt();
        }
    }
}

生产者代码

public class Task02 {
    private static final String TASK_QUEUE_NAME = "ack_queue";

    public static void main(String[] argv) throws Exception {

            Channel channel = RabbitMqUtils.getChannel();

            //生成队列
            channel.queueDeclare(TASK_QUEUE_NAME, false, false, false, null);
            //从控制台接收信息
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入信息");
            while (sc.hasNext()) {
                
                String message = sc.nextLine();
                
                channel.basicPublish("", TASK_QUEUE_NAME, null, message.getBytes("UTF-8"));
                
                System.out.println("生产者发出消息" + message);
            }
        
    }
}

消费者一号(快接收)

public class Work03 {
    private static final String ACK_QUEUE_NAME = "ack_queue";

    public static void main(String[] args) throws Exception {
        //获取信道
        Channel channel = RabbitMqUtils.getChannel();
        System.out.println("C1 等待接收消息处理时间较短");

        //消息消费的时候如何处理消息
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody());
            //睡一秒
            SleepUtils.sleep(1);
            System.out.println("接收到消息:" + message);
            /**
             * 1.消息标记 tag
             * 2.是否批量应答未应答消息
             */
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        };
        //采用手动应答
        boolean autoAck = false;
        channel.basicConsume(ACK_QUEUE_NAME, autoAck, deliverCallback, (consumerTag) -> {
            System.out.println(consumerTag + "消费者取消消费接口回调逻辑");
        });
    }
}

消费者二号(慢接收)

public class Work04 {
    private static final String ACK_QUEUE_NAME = "ack_queue";

    public static void main(String[] args) throws Exception {
        //接受信道
        Channel channel = RabbitMqUtils.getChannel();
        System.out.println("C2 等待接收消息处理时间较长");
        //消息消费的时候如何处理消息
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody());
            //睡30秒
            SleepUtils.sleep(30);
            System.out.println("接收到消息:" + message);
            /**
             * 1.消息标记 tag
             * 2.是否批量应答未应答消息
             */
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        };
        //采用手动应答
        boolean autoAck = false;
        channel.basicConsume(ACK_QUEUE_NAME, autoAck, deliverCallback, (consumerTag) -> {
            System.out.println(consumerTag + "消费者取消消费接口回调逻辑");
        });
    }
}

这时候我输入aa,bb,cc,dd,work03会马上收到aa,cc,30秒后work04收到bb,这时候我停掉work04,会发现work03接收到dd,说明dd重新入队并且被work03接收到了

不公平分发

在消费者消费队列之前 加入下面参数即可

//设置不公平分发
int prefetchCount = 1;
channel.basicQos(prefetchCount);

这时候在两个消费者都设置了这个之后,处理快的消费者会消费更多的东西

预取值

//设置预取值,预取值大于1,是几缓冲区就能放几个数据
int prefetchCount = 2;
channel.basicQos(prefetchCount);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Andrew0219

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值