MassTransit 4.X如何设置消息头?升级3.X代码失效问题
在MassTransit 4.X中设置消息头的解决方案
你遇到的问题是因为MassTransit 4.X在总线观察者注册的时机上有了调整,原来在总线创建后调用ConnectSendObserver的方式已经无法正确拦截消息发送流程。下面是具体的解决步骤:
1. 优化SendObserver实现(逻辑不变,Task返回更简洁)
你的消息头设置逻辑本身没问题,只是可以把.NET旧版的Task.FromResult<object>(null)替换为.NET 4.6+推荐的Task.CompletedTask,代码更简洁规范:
public class SendObserver : ISendObserver { public Task PostSend<T>(SendContext<T> context) where T : class { return Task.CompletedTask; } public Task PreSend<T>(SendContext<T> context) where T : class { var currentThreadIdentityObject = Thread.CurrentPrincipal.Identity is JustIMIdentity ? (Thread.CurrentPrincipal.Identity as JustIMIdentity).IdentityObject : null; if (currentThreadIdentityObject != null) { context.Headers.Set(AppSettingConfig.RabbitMqIdentityHeaderKey, currentThreadIdentityObject.StaffID); } return Task.CompletedTask; } public Task SendFault<T>(SendContext<T> context, Exception exception) where T : class { return Task.CompletedTask; } }
2. 修改Autofac注册:在总线配置阶段绑定观察者
核心变化是不要在总线创建完成后再调用ConnectSendObserver,而是把观察者注册逻辑放到CreateUsingRabbitMq的配置委托内部,这样MassTransit才能在初始化阶段把观察者挂载到消息发送管道中:
// Autofac总线注册逻辑修改 builder.Register(context => { var busControl = Bus.Factory.CreateUsingRabbitMq(cfg => { var uri = AppSettingConfig.RabbitMqBaseUri; var host = cfg.Host(new Uri(uri), x => { x.Username(AppSettingConfig.RabbitMqUserName); x.Password(AppSettingConfig.RabbitMqUserPassword); }); // 关键:在这里注册发送观察者,而非总线创建后 cfg.ConnectSendObserver(new SendObserver()); }); busControl.Start(); return busControl; }) .SingleInstance() .As<IBusControl>() .As<IBus>(); builder.RegisterGeneric(typeof(RequestClient<,>)).AsSelf().AsImplementedInterfaces();
如果你的SendObserver需要依赖其他服务(比如注入配置或仓储),可以直接从Autofac容器中解析实例:
// 从容器解析带依赖的SendObserver var sendObserver = context.Resolve<SendObserver>(); cfg.ConnectSendObserver(sendObserver);
失效原因说明
MassTransit 4.X重构了总线的初始化流程,观察者必须在总线配置阶段完成注册,才能被集成到消息发送的整个生命周期管道中。如果在总线创建完成后再调用ConnectSendObserver,观察者无法被正确绑定到发送流程,导致PreSend方法不会被触发,消息头自然无法设置。
内容的提问来源于stack exchange,提问作者BERTON.L
相关产品推荐
相关产品推荐

