RabbitMQ(11)RabbitMQ高级特性:Cosumer Ack

概述

ack指Acknowledge,确认。表示消费端收到消息后的确认方式。
有三种确认方式:

  1. 自动确认: acknowledge= “none”
  2. 手动确认: acknowledge= “manual”
  3. 根据异常情况确认: acknowledge= “auto”,(这种方式使用麻烦,并且不常用)

自动确认是指,当消息一旦被Consumer接收到,则自动确认收到,并将相应message从RabbitMQ的消息缓存中移除。但是在实际业务处理中,很可能消息接收到,业务处理出现异常,那么该消息就会丢失

如果设置了手动确认方式,则需要在业务处理成功后,调用channel.basicAck(), 手动签收,如果出现异常,则调用channel.basicNack0方法,让其自动重新发送消息

代码测试

修改配置文件
spring-rabbitmq-consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/rabbit
       http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
    <!--加载配置文件-->
    <context:property-placeholder location="classpath:rabbitmq.properties"/>

    <!-- 定义rabbitmq connectionFactory -->
    <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}"
                               port="${rabbitmq.port}"
                               username="${rabbitmq.username}"
                               password="${rabbitmq.password}"
                               virtual-host="${rabbitmq.virtual-host}"/>

<!--    定义包扫描-->
    <context:component-scan base-package="com.yy.listener" />

    <!--定义监听器容器,加载这些监听类-->
    <rabbit:listener-container connection-factory="connectionFactory" acknowledge="manual" >
       <rabbit:listener ref="ackListener" queue-names="test_queue_confirm"></rabbit:listener>
       
    </rabbit:listener-container>

</beans>

在监听类中去完成手动签收的功能
AckListener

package com.yy.listener;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * Consumer ACK机制:
 *  1. 设置手动签收。acknowledge="manual",默认是自动签收
 *  2. 让监听器类实现ChannelAwareMessageListener接口
 *  3. 如果消息成功处理,则调用channel的 basicAck()签收
 *  4. 如果消息处理失败,则调用channel的basicNack()拒绝签收,broker重新发送给consumer
 *
 *
 */

@Component
public class AckListener implements ChannelAwareMessageListener {

    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        //当前收到消息的tag标签
        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        try {
            //1.接收转换消息
            System.out.println(new String(message.getBody()));

            //2. 处理业务逻辑
            System.out.println("处理业务逻辑...");
            
            int i = 3/0;//出现错误,则broker一直会重新发送该消息给消费端
            
            //3. 手动签收
            /*
            第一个参数:当前收到消息的tag标签
            第二个参数:设置为true代表允许所有的消息被签收
             */
            channel.basicAck(deliveryTag,true);
        } catch (Exception e) {
            //e.printStackTrace();

            //4.拒绝签收
            /*
            第三个参数:requeue:重回队列。
            如果设置为true,则消息重新回到queue,broker会重新发送该消息给消费端
             */
            channel.basicNack(deliveryTag,true,true);
        
        }
    }
}

总结

在rabbit:listener-container标签中设置acknowledge属性,设置ack方式 none:自动确认,manual: 手动确认

如果在消费端没有出现异常,则调用channel.basicAck(deliveryTag,false);方法确认签收消息

如果出现异常,则在catch中调用basicNack或basicReject,拒绝消息,让MQ重新发送消息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

?abc!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值