应区分错误类型:临时性故障(如网络抖动、下游超时)可重试,业务性错误(如json解析失败、库存不足、幂等校验不通过)不可重试,需直送dlq;rabbitmq中优先用msg.nack(true, false)进死信队列,并确保队列声明时配置x-dead-letter-exchange和x-dead-letter-routing-key。

消息消费失败不是“重试就行”,而是要分清错误类型、控制重试路径、防止链路雪崩——Go 里最常踩的坑,是把所有失败都塞进同一个 Nack(true, false) 里。
如何判断该不该重试?
不是所有失败都适合重试。临时性故障(如网络抖动、下游超时、Redis 连接中断)可以重试;业务性错误(如 JSON 解析失败、字段缺失、库存不足、幂等校验不通过)重试毫无意义,只会加重问题。
- 推荐用自定义错误接口区分:
RetryableError,在processBusinessLogic返回前包装错误 - HTTP 调用失败时,优先检查
StatusCode:4xx 错误基本不可重试,5xx 或连接超时才考虑重试 - 数据库唯一键冲突、Redis WATCH 失败这类错误,说明业务状态已变更,应直接进 DLQ 或落库,而非重入队列
- 别依赖
error.Error()字符串匹配来判断——容易漏掉封装后的错误,用errors.As()检查更可靠
RabbitMQ 场景下,Nack 和 Reject 怎么选?
选错会导致消息无限循环、堆积或静默丢失。关键看语义和 requeue 行为:
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
-
msg.Nack(true, false):拒绝当前及之前所有未确认消息,且不重入队(requeue=false)——这是处理失败后进死信队列的标准姿势 -
msg.Reject(false):只拒绝当前消息,不重入队——适合明确不可恢复的错误,比如json.Unmarshal失败 -
msg.Nack(false, true)或msg.Reject(true):让消息重回队头——除非你同时做了幂等 + 指数退避 + retry_count header 控制,否则禁用 - 绝对不要在
defer里调Nack:goroutine 退出后 AMQP channel 可能已关闭,调用会 panic 或静默失败
死信队列为什么没收到消息?
常见现象是调了 Nack(true, false),但 DLQ 里空空如也。根本原因往往卡在队列声明阶段:
- 声明 normal queue 时,必须显式设置两个参数:
x-dead-letter-exchange(指向死信交换机)和x-dead-letter-routing-key(指定路由键),缺一不可 - 死信交换机(DLX)不会自动创建,得先手动声明,类型通常为
direct或topic,且需绑定到 DLQ - 如果只设了
x-message-ttl但没配 DLX,TTL 过期后消息直接被丢弃,不会进任何队列 - 检查 consumer 是否启用了
autoAck=true:这是消息丢失的头号原因,生产环境必须关掉,改用手动Ack/Nack
重试次数怎么安全地记?
用局部变量 retryCount int 计数是无效的——进程重启、goroutine 重建、消费者扩缩容都会丢掉它。RabbitMQ 不保存你的 Go 变量,只认 message 层数据。
- 优先用 message header:
msg.Headers["retry_count"],轻量、原生支持、跨队列自动携带 - 首次发送时,在
amqp.Publishing.Headers中初始化:"retry_count": 0 - 重试队列消费时,读取并递增:
count := msg.Headers["retry_count"].(int); count++ - 若
count >= 3,不再发回重试队列,而是ch.Publish("dl-exchange", "dl-routing-key", ...)进 DLQ,或直接写入dlq_events表 - 避免把重试计数塞进 JSON body:一旦解析失败,整个消息无法处理;header 失败只是字段缺失,更健壮
真正麻烦的从来不是“怎么重试”,而是“什么时候该停”。retry_count 到上限后进 DLQ,只是兜底;DLQ 自己也要有独立 consumer group、结构化日志、最大重试限制和归档机制——否则故障会从主链路蔓延到兜底链路,连最后的逃生舱都沉了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










