使用Rebus+RabbitMQ时非共享消息对象无法接收消息的解决方案咨询
解决Rebus+RabbitMQ不共享消息类的问题
当然可以不用共享消息类文件,问题的核心在于Rebus默认使用类型的完全限定名(包含命名空间、程序集版本等信息)作为消息的rbs2-type头部标识,以此匹配订阅端的消息处理程序。两端独立定义的类哪怕同名同属性,程序集信息不同,完全限定名就不一样,自然无法被正确识别。
你可以通过以下几种方式解决:
1. 统一消息类型标识规则
修改Rebus的类型命名策略,让两端用相同的规则生成消息类型标识,比如只使用类名而非完全限定名:
在发布端和订阅端的Rebus配置中添加:
Configure.TypeName(type => type.Name);
这样Rebus会只用类名(比如StringMessage)作为rbs2-type头的值,两端只要类名一致就能匹配。但要注意:如果项目中有多个同名但结构不同的消息类,会造成冲突,这种场景下建议给类加上唯一的前缀或改用命名空间+类名的组合。
2. 自定义类型映射
如果两端类的完全限定名不同,可以手动配置类型映射,告诉Rebus将某类消息映射到目标类型:
比如订阅端可以这样配置,把发布端的PubProject.StringMessage映射到本地的SubProject.StringMessage:
Configure.TypeName(type => type.FullName == "SubProject.StringMessage" ? "PubProject.StringMessage" : type.FullName );
或者使用更灵活的映射字典:
var typeMap = new Dictionary<string, Type> { ["PubProject.StringMessage"] = typeof(SubProject.StringMessage) }; Configure.TypeName(type => typeMap.TryGetValue(type.FullName, out var mappedType) ? mappedType.FullName : type.FullName);
3. 契约优先的序列化方案
使用中立的契约格式(如JSON Schema、Protobuf)定义消息结构,两端各自根据契约生成本地类,再配置Rebus的序列化器确保序列化后的内容一致:
- 比如用Newtonsoft.Json序列化时,配置忽略程序集信息:
Configure.Serialization(s => s.UseNewtonsoftJson(settings => { settings.TypeNameHandling = TypeNameHandling.None; }));
同时结合类型标识规则,确保两端用相同的标识匹配消息。
注意事项
- 无论用哪种方式,两端消息类的属性名、数据类型必须完全一致,否则会出现反序列化失败的问题。
- 如果使用Protobuf等强序列化方案,还需要确保字段的标识号(Tag)一致。
内容的提问来源于stack exchange,提问作者Michael Winther
相关产品推荐
相关产品推荐

