You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RabbitMQ的BasicdeliverEventArgs对象Body莫名变更问题求助

问题根源与解决方案

你的问题核心在于RabbitMQ客户端的BasicDeliverEventArgs对象是可能被复用的,其Body指向的是共享内存缓冲区。当你把原始的BasicDeliverEventArgs实例存入FailQueue后,后续RabbitMQ处理新消息时,可能会覆盖这块共享内存,导致你看到Body内容“自动变更”——你并没有手动修改,但底层内存被客户端复用了。

具体修复步骤:

  1. 避免直接传递BasicDeliverEventArgs对象:在从RabbitMQ获取消息时,立即复制Body的字节数组,并将需要的消息元数据(比如DeliveryTag、Exchange、RoutingKey等)封装成自定义的消息类,而不是直接使用RabbitMQ的原生对象。
  2. 修改队列存储与处理逻辑:让DataQueue和FailQueue存储自定义消息对象,而非BasicDeliverEventArgs实例。

修复后的代码示例:

首先定义自定义消息类:

public class RabbitMqMessage
{
    public byte[] Body { get; set; }
    public ulong DeliveryTag { get; set; }
    // 按需添加其他需要的元数据,比如Exchange、RoutingKey等
}

然后在读取RabbitMQ消息时,转换为自定义对象再入队:

// 从RabbitMQ接收到消息时的处理
void OnReceived(object sender, BasicDeliverEventArgs e)
{
    var customMsg = new RabbitMqMessage
    {
        Body = e.Body.ToArray(), // 复制字节数组,脱离共享缓冲区
        DeliveryTag = e.DeliveryTag
    };
    DataQueue.Enqueue(customMsg);
}

修改ProcessQueue方法:

void ProcessQueue(object obj)
{
    var msg = (RabbitMqMessage)obj;
    var cnv = new ByteArraySerializer();
    var dto = cnv.Deserialize<MyClass>(msg.Body);
    
    try
    {
        var err = Repository.Database.Insert(dto);
        if (err == null)
            Console.WriteLine("Success Sent");
        else
            FailQueue.Enqueue(msg); // 存入自定义对象,内存不会被复用
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error Occoured:" + ex);
    }
}

额外注意点:

  • 你原代码里var e.Body.ToArray();没有赋值给变量,后续直接用body是错误的,应该是var body = e.Body.ToArray();,不过这只是笔误,但核心问题还是对象复用。
  • 永远不要依赖RabbitMQ原生事件对象的长期存活,这类对象通常是为了单次消息处理设计的,底层内存会被客户端复用或回收。

内容的提问来源于stack exchange,提问作者Mostafa Asadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 14:47:43