RabbitMQ消息可靠性三板斧

RabbitMQ消息可靠性三板斧

生产环境消息不能丢,三个环节都要保证:

scss 复制代码
生产者 --(Confirm/Return)--> Broker --(持久化)--> 队列 --(手动ACK)--> 消费者

1. 生产者确认(Confirm)

application.yml 开启:

yaml 复制代码
spring:
  rabbitmq:
    publisher-confirm-type: correlated

配置回调:

typescript 复制代码
@Configuration
public class RabbitConfig implements RabbitTemplate.ConfirmCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack) {
            System.out.println("消息成功到达 Exchange");
        } else {
            System.err.println("消息丢失: " + cause);
            // TODO: 补偿重发或记录数据库
        }
    }
}

2. 消息退回(Return)

当 Exchange 无法路由到 Queue 时触发:

typescript 复制代码
@Configuration
public class RabbitConfig implements RabbitTemplate.ReturnsCallback {

    @PostConstruct
    public void init() {
        rabbitTemplate.setReturnsCallback(this);
    }

    @Override
    public void returnedMessage(ReturnedMessage returned) {
        System.err.println("路由失败: " + returned.getMessage());
        // TODO: 报警或转存
    }
}

发消息时指定 mandatory = true:

arduino 复制代码
rabbitTemplate.convertAndSend(
    "exchange", "routingKey", msg,
    message -> message,  // MessagePostProcessor
    new CorrelationData("id-001")
);

3. 队列与消息持久化

typescript 复制代码
@Bean
public Queue durableQueue() {
    // durable=true 队列持久化
    return QueueBuilder.durable("durable.queue").build();
}

消息持久化:

ini 复制代码
MessageProperties props = new MessageProperties();
props.setDeliveryMode(MessageDeliveryMode.PERSISTENT); // 2 = 持久化

Message message = new Message("hello".getBytes(), props);
rabbitTemplate.convertAndSend("exchange", "key", message);

4. 消费者手动 ACK

application.yml:

yaml 复制代码
spring:
  rabbitmq:
    listener:
      simple:
        acknowledge-mode: manual  # 手动确认
        prefetch: 1               # 每次只取1条,处理完再取下一条

消费者代码:

java 复制代码
@Component
public class AckConsumer {

    @RabbitListener(queues = "durable.queue")
    public void receive(Message message, Channel channel) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            String body = new String(message.getBody());
            System.out.println("处理: " + body);
            // 业务逻辑...
            
            // 手动确认
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            // 拒绝并重新入队(根据业务决定是否重试)
            channel.basicNack(deliveryTag, false, true);
        }
    }
}

小结:Confirm 防丢失到 Exchange,Return 防路由失败,持久化防 Broker 重启丢数据,手动 ACK 防消费者处理失败丢消息。四者结合,消息可靠性基本稳了。

相关推荐
打工仔折腾 AI2 分钟前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
汉堡大王952718 分钟前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端
武子康1 小时前
ESP32 唤醒成功,离线命令为什么没有执行?
人工智能·后端·agent
挖掘狂人1 小时前
SQL 注入:一行代码如何撬开整个数据库
后端·sql·数据分析
今年下半年1 小时前
【短信发送】Spring Boot整合多种短信接口的实现(附源码)
java·spring boot·后端·sms·qcloudsms
不爱吃鱼的蔓热莓1 小时前
Autosar之统计SWC中port、runnable、信号名等信息(三)
后端·restful
北城笑笑2 小时前
Server 18 ,Nginx 双服务器 HTTP转HTTPS 代理实战( HTTP 地址换 HTTPS 域名 )
运维·服务器·前端·后端·nginx·http·https
紫洋葱hh2 小时前
Go 入门基础:类型、变量与运算符
开发语言·后端·ai·golang
打工仔折腾 AI2 小时前
Qt网络编程实战:UDP、TCP到HTTP的落地经验与选型
网络·人工智能·后端·python·qt·udp·ai agent 实战
打工仔折腾 AI2 小时前
SQL 编辑器不是高级记事本:KStudio 与 KSQL Developer 的建表与增删改查手法
数据库·人工智能·后端·python·sql·编辑器·ai agent 实战