在.NET Core中如何使用RabbitMQ.Client告知RabbitMQ任务执行失败
问题解决说明
你当前代码的核心问题是调用BasicGet方法时第二个参数传入了true,这代表开启了**自动确认(autoAck)**模式,此时RabbitMQ只要把消息投递给消费者,就会直接将消息从队列中删除,不会管后续业务逻辑是否执行成功,这种模式下你没办法通知RabbitMQ任务执行失败。
修正步骤
- 首先关闭自动确认,将
BasicGet的第二个参数改为false - 业务执行成功时,手动调用
BasicAck确认消息,通知RabbitMQ可以删除该消息 - 业务执行失败时,调用
BasicNack或者BasicReject通知RabbitMQ任务失败,同时选择是否将消息重新放回队列
核心API说明
BasicAck(deliveryTag, multiple):手动确认消息消费成功deliveryTag:当前消息的唯一标识,从拉取到的消息包的DeliveryTag属性获取multiple:是否批量确认,传false仅确认当前单条消息
BasicNack(deliveryTag, multiple, requeue):通知RabbitMQ消息消费失败requeue:是否将消息放回队列头部重新投递,传true会重试,传false消息会被直接删除或进入死信队列
修正后的代码示例
var channel = RabbitPrepareFactory.GetConnectionFactory(); channel.BasicQos(0, 1, false); // 关闭自动确认,第二个参数改为false var notificationPack = channel.BasicGet("notification", false); var message = System.Text.Encoding.UTF8.GetString(notificationPack.Body.ToArray()); var task = JsonConvert.DeserializeObject<ForgetPasswordEmailNotification>(message); var isEmailSendSuccessful = SomeFakeEmailSendFunctions(task.Email); if (isEmailSendSuccessful) { // 业务成功,手动确认消息 channel.BasicAck(notificationPack.DeliveryTag, false); } else { // 业务失败,通知RabbitMQ,requeue设为true将消息放回队列重试 // 如果确定该消息永远无法处理成功,可以将requeue设为false,避免无限重试 channel.BasicNack(notificationPack.DeliveryTag, false, requeue: true); }
常见疑问解答
- Q:RabbitMQ.Client能不能自动识别业务失败状态?
A:不能,业务成功/失败是你自己的业务逻辑定义的,框架无法感知,必须你自己根据业务返回结果手动调用对应的确认方法。 - Q:是不是必须手动触发ack相关操作?
A:是的,只有关闭autoAck之后手动调用确认接口,RabbitMQ才会知道消息的消费状态,否则开着autoAck的话所有消息拿出来就直接被删除了。
内容的提问来源于stack exchange,提问作者Emre Ceyhan
相关产品推荐
相关产品推荐

