RabbitMq高级特性:消息确认,持久化,重试机制

本篇博客基于SpringBoot + Spring AMQP来写,代码实现和API调用均使用Spring AMQP的封装展开,和原生amqp-client SDK原理一致,但代码实现会有所不同

目录

一,消息确认

1.1发送方确认

[1.1.1 Confirm模式](#1.1.1 Confirm模式)

[1.1.2 returns模式](#1.1.2 returns模式)

1.2接收方确认

二,持久化

1,交换机持久化

2,队列持久化

3,消息持久化

三,重试机制

四,RabbitMq如何保证消息可靠传输

1,生产端

2,Broker端

3,消费端

五,

在发送方确认过程中,如果有多条消息,如何知道是哪条消息?

2,如果消息处理过程中发生了死锁,一直无法调用basicAck会出现什么问题?


一,消息确认

消息确认分为生产者确认和消费者确认

1.1发送方确认

生产者确认分为 confirm 和 returns两种模式,两种模式在不同的过程中发挥作用

1.1.1 Confirm模式

producer在发送消息时,会在发送端设置设置一个CofirmCallback监听,无论消息是否到达交换机,,监听都会被执行,如果交换机收到,ACK就为true,反之则为false

首先对项目进行配置

设置回调方法

1.1.2 returns模式

消息到达交换机,在根据路由规则进行匹配时,交换机到队列的过程中,如果消息无法被任何对队列消费(没有相匹配的队列或者队列不存在),就可以选择把消息退回个生产者,在这个过程中同样通过设置回调函数对消息进行处理。

配置参考confirm模式,二者相同。

设置回调函数:

Mandatory属性默认是false,confirmCallback和returnsCallback应该在同一个rabbitTemplate中设置

1.2接收方确认

spring AMQP对消息确认机制提供了三种策略

AcknowledgeMode.NONE:消息一旦发送给消费者,不管接收方是否成功处理了消息,RabbitMq会自动确认消息并从队列中移除消息,消息处理失败可能会丢失。

AcknowledgeMode.AUTO(默认):消费者成功处理消息时会自动确认,如果处理过程中出现了异常则不会确认消息。

AcknowledgeMode.MANUAL:消费者需要手动调用basicAck方法来确认消息,如果消息未被确认,RabbitMq会认为消息未被处理成功,还在消费者可用时重新投递消息,提高了消息处理的可靠性,后续如果消息仍然被处理失败没消息也不会丢失。

配置确认机制

AUTO模式:

项目启动可以看到RabbitMq在一致向消费者投递消息

NONE模式:

当我们改成NONE模式,该模式RabbitMq不管消费方是否收到消息都会把消息从队列中移除

项目一启动,消费者就会收到消息,不管是否出现异常。

MANUAL模式:

项目启动日志在一直滚动,因为我们这里代码逻辑设置为出现异常重新入队,RabbitMq就会一直投递消息给消费者

同时可以看到ack.queue有一条Unacked的消息

二,持久化

持久化分为交换机持久化,队列持久化,消息持久化

1,交换机持久化

2,队列持久化

3,消息持久化

总结:通过消息持久化可以哦解决因为服务器异常崩溃而导致的消息丢失,但是如果当生产者把消息发送出去之后,消息在到达服务器之前已经丢失(服务器重启,消息投递失败)就需要通过发送方确认来解决

三,重试机制

消息传递过程中,如果出现网络故障,服务器故障,资源不足等问题,就可能导致消息处理失败,重试机制则允许消息在处理失败后重新发送,程序逻辑错误除外。

配置:

在自动模式下,异常没被捕获

项目启动后会按照配置项配置的次数重试,如果异常捕获则不会重试,而在手动模式下,需要手动对消息确认,出现异常可以选择是否重新入队,控制权在应用本身,不受配置的限制

四,RabbitMq如何保证消息可靠传输

1,生产端

生产端到交换机:首先生产端方面,配置异步确认,设置回调函数,当broker收到消息之后,触发回调,记录日志,并根据broker的响应判断是否收到消息,做进一步处理。

交换机到队列 :首先setMandatory 告诉broker如果消息没有队列接受需要返回给生产者,同样设置回调监听,在消息路由失败时,可以拿到失败原因,并且可以在回调函数中设置进一步的补偿逻辑。

2,Broker端

在创建交换机,队列时给设置持久化。发送消息时给消息设置持久化,调用setDeliveryMode设置消息是否持久化

3,消费端

**手动确认:**通过配置acknowledge-mode的模式为manual,在监听到消息之后,业务逻辑执行成功调用basicAck()方法显式确认,业务出现异常调用执行basicNack()方法,让消息进入死信队列进行该兜底,防止无限重试引发死循环。

本地重试机制:配置消息自动进行重试的依赖,并限制重试次数,从而避免因网络原因导致消息直接进入死信队列。重试次数后还没正常消费则执行Nack流程

五,

在发送方确认过程中,如果有多条消息,如何知道是哪条消息?

在消息发送时设置 CorrelationData 设置消息ID,当触发回调时,会原封不动的拿到CorrelationData,从而可以拿到消息ID

2,如果消息处理过程中发生了死锁,一直无法调用basicAck会出现什么问题?

如果消息一直处于Unacked的状态,当消费者进程或者网络断开时。RabbitMq会将这条消息重新放回队列,交给其他消费者处理。

相关推荐
君顾11 小时前
外卖CPS小程序开发实战指南:从零到上线的完整流程
java·开发语言·外卖
流烟默1 小时前
xxl-job 接入 Spring 的两种方式:手动装配与自动装配(含 initMethod 双启动踩坑实录)
java·spring·xxl-job
鹅城剑仙1 小时前
Spring Boot 3 全局异常处理与统一响应封装进阶实战
java·spring boot·后端
橘子汽水1681 小时前
Leetcode 208,207实现Trie前缀树,课程表
java·数据结构·算法·leetcode
tryxr1 小时前
Chat2Excel 文件服务模块剩余功能开发
java·服务器·windows·java项目·文件服务
张小姐的猫1 小时前
【AI大模型接入SDK】 —— Ollama本地接入Deepseek
java·linux·开发语言·网络·c++·人工智能
谢亮_vipxieliang1 小时前
ValidX与Maven/Gradle集成配置指南
java·spring boot·spring·maven·hibernate
Nuanyt1 小时前
JUC常见核心知识梳理01 线程 并发 JMM volatile 管程 锁 synchronized
java·开发语言·网络·jvm
我命由我123451 小时前
Android 控件 - ListAdapter
android·java·java-ee·android studio·android jetpack·android-studio·android runtime