RabbitMQ_消息确认机制
创始人
2024-03-19 20:14:38

消息确认机制分为消息发送确认机制消息消费确认机制

消息发送确认机制

消息发送确认机制:消息由producer发送后,确认其是否到达broker,又是否被exchange转发至对应queue的机制

该机制分为两部分:producer---broker,exchange---queue

前者的实现依靠ConfirmCallback机制,后者的实现依靠ReturrnsCallback机制

ConfirmCallback

实现ConfirmCallback接口,并重写confirm方法

confirm方法参数含义:

correlationData:CorrelationData类只有一个 id 属性 用于唯一标识该消息
public CorrelationData() {this.id = UUID.randomUUID().toString();
}ack:消息是否成功传输到 broker (true表示成功传输 false表示传输失败)cause:传输失败的原因

当消息传输至broker后就会触发ConfirmCallback回调,无论传输是否成功,可根据传输的结果进行后续处理

@Component
// ConfirmCallback 用于确认消息是否到达 broker(rabbitmq服务器)
// 实现 ConfirmCallback 接口 重写confirm()方法
public class ConfirmCallbackComponent implements RabbitTemplate.ConfirmCallback {/*correlationData:CorrelationData类只有一个 id 属性 用于唯一标识该消息public CorrelationData() {this.id = UUID.randomUUID().toString();}ack:消息是否成功传输到 broker (true表示成功传输 false表示传输失败)cause:传输失败的原因*/@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {if (!ack) {System.out.println("消息发送异常");} else {System.out.println("消息发送成功" + " correlationData=" + correlationData.getId() + " ack=" + ack + " cause=" + cause);}}
}

ReturrnsCallback

实现ReturnsCallback接口,并重写returnedMessage方法

当消息转发失败后就会触发ReturrnsCallback,会将消息返回给生产者,同时会返回与消息转发失败的相关信息(包含在参数returned内),可对此采取后续处理

@Component
// 实现ReturnCallback接口 重写returnedMessage()方法
public class ReturnsCallbackComponent implements RabbitTemplate.ReturnsCallback {@Overridepublic void returnedMessage(ReturnedMessage returned) {System.out.println("ReturnCallback: replyCode=" + returned.getReplyCode() + " replyText=" + returned.getReplyText() + " message= " + returned.getMessage() + " exchange=" + returned.getExchange() + " routingKey=" + returned.getRoutingKey());}
}

配置文件

注:生产者端配置文件

ConfirmCallback

publisher-confirm-type: correlated#NONE:#禁用发布确认 是默认值。#CORRELATED:#发布消息后 交换机会触发回调方法。#SIMPLE:#有两种效果:#1:和CORRELATED一样会触发回调方法#2:发布消息成功后使用 rabbitTemplate 调用 waitForConfirms 或 waitForConfirmsOrDie 方法等待 broker 节点返回发送结果#根据返回结果来判定下一步的逻辑: waitForConfirmsOrDie 方法如果返回 false 则会关闭 channel 则接下来无法发送消息到 broker

ReturnsCallback

    template:mandatory: true # 设置当交换机分发消息失败时 将消息返回至生产者(否则直接丢弃)publisher-returns: true # 允许消息返回至生产者

消息消费确认机制

生产者Service

此处需要调用ConfirmCallback接口与ReturnsCallback接口的实现类实例

@Service
public class WorkService {@Autowiredprivate RabbitTemplate rabbitTemplate;@Autowiredprivate ConfirmCallbackComponent confirmCallbackComponent;@Autowiredprivate ReturnsCallbackComponent returnsCallbackComponent;public void sendMessage(String exchange, String routingKey, Object msg) {// 消息被手动ack时的处理rabbitTemplate.setConfirmCallback(confirmCallbackComponent);// 消息重返队列时的处理rabbitTemplate.setReturnsCallback(returnsCallbackComponent);// 发送消息rabbitTemplate.convertAndSend(exchange, routingKey, msg,// 是否持久化消息message -> {message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);return message;},// 实现ConfirmCallback接口 重写其confirm方法时 作为confirm方法的参数new CorrelationData(UUID.randomUUID().toString()));}
}

消费者Service

deliveryTag:表示消息投递序号 接收消息后deliveryTag++
手动确认模式下 我们可以对指定deliveryTag的消息进行ack、nack、reject等操作multiple:是否批量确认消息 值为true则会一次性ack所有小于当前消息deliveryTag的消息
举个栗子:假设已发送三条消息 deliveryTag分别是1、2、3 但均未被确认此时发送第四条消息 其deliveryTag为4 且该消息被确认若multiple被设置为true 则会将1、2、3、4的消息全部进行确认requeue:消息是否重入队列 true为重入方法参数: 
basicAck: deliveryTag multiple
basicReject: deliveryTag requeue
basicNack: deliveryTag multiple requeue
@Service
@RabbitListener(queues = "work_confirm_queue")
public class WorkerService {@RabbitHandlerpublic void workerMessage(String msg, Channel channel, Message message) throws IOException {/*deliveryTag:表示消息投递序号 接收消息后deliveryTag++手动确认模式下 我们可以对指定deliveryTag的消息进行ack、nack、reject等操作multiple:是否批量确认消息 值为true则会一次性ack所有小于当前消息deliveryTag的消息举个栗子:假设已发送三条消息 deliveryTag分别是1、2、3 但均未被确认此时发送第四条消息 其deliveryTag为4 且该消息被确认若multiple被设置为true 则会将1、2、3、4的消息全部进行确认requeue:消息是否重入队列 true为重入方法参数:basicAck: deliveryTag multiplebasicReject: deliveryTag requeuebasicNack: deliveryTag multiple requeue*/try {System.out.println("worker收到消息: " + msg);channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); // 确认消息}  catch (Exception e) {// 判断消息是否已重返过队列if (message.getMessageProperties().getRedelivered()) {System.out.println("worker再次接收消息失败 队列拒绝消息的重返 " + msg);channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); // 拒绝消息重返} else {System.out.println("worker接收消息失败 消息将返回队列 " + msg);channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true); // 消息重入队列}}}
}

配置文件

注:消费者端配置文件

    listener:simple:prefetch: 1 # 消费者一次性可以消费的最大消息数acknowledge-mode: manual # 开启手动应答# none 一律视为应答# manual 手动应答# auto 自动应答(与none区别在于有应答条件)retry:enabled: true # 开启重试max-attempts: 10 # 最大重试数(若使用try-catch 则该设置失效)initial-interval: 1000ms # 重试间隔

测试

关于sleep方法:单元测试运行完毕后即关闭,而调用方法与进行通信需要时间,为了确保能收到消费者端的应答,需要保证信道处于开启状态,故sleep

    @AutowiredWorkService workService;@Testvoid workQueuesOrders() throws InterruptedException {workService.sendMessage("", "work_confirm_queue", "hello");TimeUnit.SECONDS.sleep(5);}

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...