MSMQ适用于单机或局域网内Windows服务间通信,无需额外部署;RabbitMQ适用于跨平台、高可用、需Web管理及AMQP协议的分布式场景。

Windows 自带的 MessageQueue(MSMQ)和 RabbitMQ 是两类完全不同的东西:前者是本地 Windows 服务组件,后者是独立部署的开源消息中间件。直接混用会导致连接失败、序列化异常或“队列不存在”这类错误。
怎么判断该用 MSMQ 还是 RabbitMQ
看部署环境和协作范围:
- 单机或局域网内 Windows 服务间通信,且不希望额外装服务 → 用
MessageQueue(需启用“Microsoft Message Queue Server”Windows 功能) - 跨平台(Linux/macOS)、需要高可用、持久化、死信队列、Web 管理界面 → 必须用 RabbitMQ
- 项目已上线、突然要加消息解耦,但运维不允许开新端口或装新服务 → 只能退回到
MessageQueue
别被“消息队列”四个字骗了——MessageQueue 不支持 AMQP 协议,RabbitMQ 客户端库(如 RabbitMQ.Client)也完全无法连上 .\Private$\MyQueue 这种路径。
用 MessageQueue 创建私有队列并发送字符串
必须先确保队列存在,否则 Send() 会抛 MessageQueueException:“找不到队列”。不能靠 new 就自动创建。
- 检查并创建队列:
if (!MessageQueue.Exists(@".\Private$\MyQueue")) MessageQueue.Create(@".\Private$\MyQueue"); - 设置格式器,否则接收时会报
Cannot deserialize the message:queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); - 发送时别传裸字符串:
queue.Send("hello", "log");比queue.Send("hello")更稳妥,标签(label)可辅助排查 - 路径中的
.\Private$\MyQueue是硬编码格式,Private$不能写成private$或漏掉$,大小写不敏感但符号必须全对
用 RabbitMQ.Client 发送/接收 JSON 消息
必须用 NuGet 安装 RabbitMQ.Client(v6.8+),且 RabbitMQ 服务必须已运行(默认 http://localhost:15672 可访问管理页)。
- 连接字符串不是路径,而是
amqp://guest:guest@localhost:5672;密码默认guest,首次登录后建议改 - 发送前必须声明队列:
channel.QueueDeclare("my_queue", durable: true, exclusive: false, autoDelete: false, arguments: null);,否则消息发出去就丢了 - 发送 JSON 时手动序列化:
var body = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new { ts = DateTime.UtcNow, value = 42 }));,别依赖IBasicProperties.ContentType自动识别 - 接收端要用
channel.BasicConsume+ 手动反序列化,channel.BasicGet是同步阻塞式,容易卡住,生产环境禁用
常见踩坑点:序列化与线程安全
MessageQueue 默认用 BinaryMessageFormatter,但 .NET Core/.NET 5+ 已移除二进制序列化支持,强制设 XmlMessageFormatter 或 JsonMessageFormatter(需自己实现)。
- RabbitMQ 的
IModel(即channel)不是线程安全的,一个 channel 被多个线程BasicPublish会出错;应为每个线程或每个业务逻辑分配独立 channel - MSMQ 的
Receive()是阻塞调用,没消息时会一直等,务必配合TimeSpan.FromSeconds(5)参数,否则服务启动就卡死 - 两者都不处理“消息重试语义”:RabbitMQ 需手动
channel.BasicNack并配置死信交换器;MSMQ 需自己读message.AppSpecific判断失败次数
真正难的从来不是“怎么发”,而是“发丢了谁负责”“重复了怎么幂等”“宕机了消息还在不在”——这些得靠队列选型、ACK 策略和业务层补偿逻辑一起兜底,不是换一个 Send 方法就能解决的。











