如何避免MassTransit为抽象基类创建不必要的RabbitMQ交换机
如何避免MassTransit为抽象基类IntegrationEvent创建RabbitMQ交换机?
我在.NET 6 API中使用MassTransit + RabbitMQ实现消息发布与消费,定义了抽象基类IntegrationEvent作为所有事件的公共父类,仅需发布Event1和Event2两个具体事件类型。但发现如果不在消息拓扑配置中添加IntegrationEvent的配置,RabbitMQ就会自动创建对应的IntegrationEvent交换机,目前必须配置基类才能避免这个问题,想知道有没有无需配置基类就能阻止该交换机创建的方法。
消息层级代码
public abstract class IntegrationEvent { public string Code { get; } public DateTime DateTime { get; } public IntegrationEvent(string code) { Code = code; DateTime = DateTime.UtcNow; } } public class Event1 : IntegrationEvent { public string DataEvent1 { get; set; } = ""; Event1(string dataEvent1) : base("Event1") { DataEvent1 = dataEvent1; } } public class Event2 : IntegrationEvent { public string DataEvent2 { get; set; } = ""; Event2(string dataEvent2) : base("Event2") { DataEvent2 = dataEvent2; } }
当前拓扑配置代码
public static class ConfigurationExtensions { public static void ConfigureMessageTopology(this IRabbitMqBusFactoryConfigurator configurator) { // Primary exchanges names. configurator.Message<IntegrationEvent>(x => x.SetEntityName("service.publisher")); configurator.Message<Event1>(x => x.SetEntityName("service.publisher")); configurator.Message<Event2>(x => x.SetEntityName("service.publisher")); } }
解决方案
方法一:给抽象基类添加[ExcludeFromTopology]特性
这是最简单的方式,直接在抽象基类上标记该特性,MassTransit会自动忽略此类型的拓扑创建,无需再配置基类的消息拓扑:
using MassTransit; [ExcludeFromTopology] public abstract class IntegrationEvent { // ... 原有代码 }
之后只需要保留具体事件的配置即可:
public static void ConfigureMessageTopology(this IRabbitMqBusFactoryConfigurator configurator) { configurator.Message<Event1>(x => x.SetEntityName("service.publisher")); configurator.Message<Event2>(x => x.SetEntityName("service.publisher")); }
方法二:显式禁用基类的拓扑配置
如果不想使用特性,可以在拓扑配置中显式禁用抽象基类的拓扑创建逻辑:
public static void ConfigureMessageTopology(this IRabbitMqBusFactoryConfigurator configurator) { configurator.Message<IntegrationEvent>(x => { x.ConfigureTopology = false; // 阻止创建该类型的拓扑 x.SetEntityName(null); // 清空实体名称 }); configurator.Message<Event1>(x => x.SetEntityName("service.publisher")); configurator.Message<Event2>(x => x.SetEntityName("service.publisher")); }
方法三:自定义消息类型转换器(全局过滤)
如果需要全局过滤所有抽象基类的拓扑创建,可以实现IMessageTypeConverter来排除抽象类型:
using MassTransit; public class FilterAbstractBaseTypesConverter : IMessageTypeConverter { public IEnumerable<Type> GetMessageTypes(Type type) { // 仅返回非抽象的具体类型 var messageTypes = new List<Type>(); if (!type.IsAbstract) messageTypes.Add(type); return messageTypes; } } // 在总线配置中注册该转换器 configurator.SetMessageTypeConverter(new FilterAbstractBaseTypesConverter());
问题原因说明
MassTransit默认会遍历消息类型的整个继承层次结构,为每个基类(包括抽象基类)创建对应的RabbitMQ交换机。当发布Event1或Event2时,框架会识别到它们的基类IntegrationEvent,并尝试为其创建交换机,除非通过上述方式显式排除。
内容的提问来源于stack exchange,提问作者Jorge
相关产品推荐
相关产品推荐

