MassTransit动态发布JSON事件时所有消费者被触发且消息为空问题
问题根因排查
- 无类型反序列化导致消息类型元数据丢失:你调用
JsonConvert.DeserializeObject(json, new JsonSerializerSettings { })时未指定目标类型,返回的是System.Object类型实例。MassTransit默认会根据消息的CLR类型生成消息类型标识头,此时消息会被标记为System.Object,所有订阅了基类/通用类型的消费者都会被匹配到。 - 手动修改ContentType造成序列化冲突:你已经全局配置了
UseRawJsonSerializer(),不需要在Send委托里手动修改Serializer.ContentType.MediaType,多余操作会破坏MassTransit自带的序列化上下文。 - 动态消息缺少显式类型绑定:你要发布的是
DynamicEvent类型消息,但传递的是无类型object实例,MassTransit无法将消息和DynamicEvent的订阅做精准匹配,反而会把所有兼容object的消费者全部触发,同时消费端反序列化时因为缺少类型映射,拿到的就是空对象。
修复方案
场景1:已预定义DynamicEventCLR类
直接在反序列化时显式指定类型即可:
using var scope = _serviceScopeFactory.CreateScope(); var sendEndpointProvider = scope.ServiceProvider.GetService<ISendEndpointProvider>(); var endpoint = await sendEndpointProvider.GetSendEndpoint(new System.Uri("exchange:IntegrationEvents.DynamicEvent:DynamicEvent")); var json = JsonConvert.SerializeObject(dynamicObject, Newtonsoft.Json.Formatting.None); // 显式指定反序列化目标类型 var obj = JsonConvert.DeserializeObject<DynamicEvent>(json); await endpoint.Send(obj);
场景2:无预定义CLR类,需要发布纯动态JSON
直接调用SendJson重载,同时显式指定消息类型头避免错误匹配:
using var scope = _serviceScopeFactory.CreateScope(); var sendEndpointProvider = scope.ServiceProvider.GetService<ISendEndpointProvider>(); var endpoint = await sendEndpointProvider.GetSendEndpoint(new System.Uri("exchange:IntegrationEvents.DynamicEvent:DynamicEvent")); var json = JsonConvert.SerializeObject(dynamicObject, Newtonsoft.Json.Formatting.None); // 直接发送JSON字符串,显式绑定消息类型 await endpoint.SendJson<DynamicEvent>(json, context => { context.SetMessageType(typeof(DynamicEvent)); });
注意:需保证发送端和消费端都全局配置
cfg.UseRawJsonSerializer(isDefault: true),两端序列化规则保持一致。
内容的提问来源于stack exchange,提问作者Jb_Dda
相关产品推荐
相关产品推荐

