EasynetQ bus.Subscribe无响应,抛出'messageType must not be null'异常求助
解决EasyNetQ "messageType must not be null" 错误问题
从你的错误日志和代码来看,核心问题是EasyNetQ在反序列化消息时,无法根据消息属性里的Type值匹配到对应的CLR类型,导致抛出ArgumentNullException。下面是具体的排查和解决步骤:
1. 确认发布/订阅端的消息类型完全一致
你的消息Type属性显示为Milkshop.Common.MilkOrderRequest:Milkshop.Common,这说明发布端的MilkOrderRequest类型属于Milkshop.Common程序集。请务必确保:
- 订阅端引用的是同一个类库中的
MilkOrderRequest,而非复制代码重新定义的类型 - 两端的程序集名称、版本、强签名状态完全一致(如果启用了强签名)
如果是跨服务场景,建议把消息类型封装在独立的类库NuGet包中,让发布和订阅端统一引用,从根源避免类型不匹配问题。
2. 显式配置消息类型映射
如果两端的类型全名存在差异(比如程序集版本不同),可以自定义类型名称序列化规则,让EasyNetQ能正确映射类型:
自定义TypeNameSerializer
在发布和订阅端都配置这个自定义序列化器:
// 创建Bus时注册自定义类型序列化器 var bus = RabbitHutch.CreateBus("host=192.168.153.128:5672;username=user;password=pass", x => { x.Register<ITypeNameSerializer, FixedTypeNameSerializer>(); }); // 自定义实现 public class FixedTypeNameSerializer : ITypeNameSerializer { public string Serialize(Type type) { // 给MilkOrderRequest指定一个固定的短名称 if (type == typeof(MilkOrderRequest)) return "MilkOrderRequest"; // 其他类型保留默认规则 return type.AssemblyQualifiedName; } public Type Deserialize(string typeName) { // 把短名称映射回实际CLR类型 if (typeName == "MilkOrderRequest") return typeof(MilkOrderRequest); return Type.GetType(typeName); } }
3. 修复发布端的消息属性配置
你的发布代码未设置ContentType,EasyNetQ默认使用JSON序列化,建议显式配置,同时确保Type属性和订阅端规则一致:
using (IAdvancedBus bus = RabbitHutch.CreateBus("host=192.168.153.128:5672;username=user;password=pass").Advanced) { IExchange exchange = bus.ExchangeDeclare("milk.api", ExchangeType.Topic); IQueue queue = bus.QueueDeclare("milkorderqueue"); IBinding binding = bus.Bind(exchange, queue, "#"); var message = new Message<MilkOrderRequest>(milkOrder); // 显式指定JSON内容类型 message.Properties.ContentType = "application/json"; // 使用自定义的统一类型名称 message.Properties.Type = "MilkOrderRequest"; bus.Publish<MilkOrderRequest>(exchange, "#", true, message); } return new HttpResponseMessage(System.Net.HttpStatusCode.OK);
4. 简化订阅端代码(使用IBus而非AdvancedBus)
如果不需要AdvancedBus的高级功能,用普通的IBus.Subscribe更简洁,同时确保配置和发布端一致:
IBus bus = RabbitHutch.CreateBus(@"host=192.168.153.128:5672;username=user;password=pass", x => { x.Register<ITypeNameSerializer, FixedTypeNameSerializer>(); }); bus.Subscribe<MilkOrderRequest>("my_subscription_id", message => { Console.WriteLine($"Order recieved: {message.Milk}."); }, config => { config.WithQueueName("milkorderqueue"); });
错误根源总结
EasyNetQ依赖消息的Type属性定位反序列化所需的CLR类型,以下情况都会触发这个异常:
- 订阅端未引用包含目标类型的程序集
- 消息
Type属性的值与订阅端的类型全名不匹配 - 程序集加载异常(比如版本冲突导致无法加载类型)
内容的提问来源于stack exchange,提问作者Noobie3001
相关产品推荐
相关产品推荐

