.NET Framework 4.8下MassTransit对接RabbitMQ发布消息失败问题求助
核心问题排查与修正
已定位的根因
- 发布端使用
async void作为控制台程序入口的异步方法,Main线程调用后没有可等待的Task对象,会直接退出进程,所有循环内的异步消息发送操作没有执行窗口,连异常都来不及抛出,进程就被系统回收。 - 循环逻辑设计完全冗余:10000次循环的每一次迭代都重新创建、启动、停止整套Bus实例,反复建立RabbitMQ连接、创建通道,频繁的连接中断会直接打断消息投递链路。
- 没有等待异步任务完成就触发资源释放:因为
async void的上下文缺失,await busControl.Publish(message)还未完成投递,就会进入finally块执行busControl.Stop(),直接中断发送流程。 - 全量注释了日志初始化逻辑,MassTransit运行时的内部错误(连接握手失败、路由不匹配、序列化异常)会被静默丢弃,没有任何可追溯的错误输出。
修正后的发布端实现
internal class Send { // 控制台入口兼容async Task签名,会自动等待所有异步操作执行完成 public static async Task Main(string[] args) { IBusControl busControl = null; try { // 全流程仅创建一次Bus实例 busControl = Bus.Factory.CreateUsingRabbitMq(sbc => { sbc.Host(new Uri("rabbitmq://localhost"), h => { h.Username("guest"); h.Password("guest"); }); }); // 异步启动Bus,等待RabbitMQ连接完全建立 await busControl.StartAsync(); for (var i = 0; i < 10000; i++) { var message = new ValueEntered { Value = $"Message {i}" }; // 复用已建立的连接发布消息 await busControl.Publish(message); Console.WriteLine($"Published [x] : {message.Value} [at] {DateTime.Now:u}"); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } finally { // 所有消息发送完成后再统一停止连接 if (busControl != null) await busControl.StopAsync(); } Console.ReadLine(); } }
订阅端同步调整细节
- Bus的启动、停止同样替换为
StartAsync()/StopAsync()异步方法,避免同步阻塞导致RabbitMQ连接建立不完整、队列绑定失败的问题。 - 确认发布端、订阅端引用的是同一个
Contracts项目程序集,避免因为同名字符串类型的程序集上下文不一致,导致MassTransit无法匹配路由规则。 - 链路验证:启动发布端后在RabbitMQ管理后台检查和
Contracts.ValueEntered全限定名同名的持久化Exchange的入站消息计数,如果计数为0,说明消息根本没有投递到Exchange,对应上述提到的进程提前退出、连接被提前中断的问题。
内容的提问来源于stack exchange,提问作者Rohith Venkat
相关产品推荐
相关产品推荐

