如何用MassTransit+Autofac替代WCF的ServiceHost实现服务启动
问题核心原因
你当前的实现存在两个核心缺失,导致消费者没有实际运行:
- 未配置MassTransit的消息传输组件(如RabbitMQ、内存传输等),框架不知道使用什么协议、什么地址监听消息
- 未配置接收端点(ReceiveEndpoint),已经注册的消费者没有绑定到对应的监听队列,自然不会处理请求,等价于WCF只声明了服务类没有配置服务监听地址
正确实现代码
以下是适配RabbitMQ(最常用的MassTransit传输方案)的实现,如果你使用其他传输组件,替换对应UsingXXX配置即可:
// 把IBusControl声明为类全局变量,避免被GC回收,等价于原来的ServiceHost变量 private IBusControl _busControl; public void StartService() { var builder = new ContainerBuilder(); // 如果项目已有全局Autofac容器,直接用已有的ContainerBuilder注册即可,不要新建 builder.AddMassTransit(config => { // 注册两个服务对应的消费者 config.AddConsumer<TeamTimeManager>(); config.AddConsumer<TeamTimeUtilityManager>(); // 配置RabbitMQ传输,替换成你实际的消息队列配置 config.UsingRabbitMq((context, cfg) => { cfg.Host("你的RabbitMQ地址", "/", h => { h.Username("你的账号"); h.Password("你的密码"); }); // 配置第一个服务的接收端点,对应原来的第一个ServiceHost cfg.ReceiveEndpoint("team-time-service", e => { // 绑定TeamTimeManager消费者到这个队列 e.ConfigureConsumer<TeamTimeManager>(context); }); // 配置第二个工具服务的接收端点,对应原来的第二个utilHost cfg.ReceiveEndpoint("team-time-utility-service", e => { // 绑定TeamTimeUtilityManager消费者到这个队列 e.ConfigureConsumer<TeamTimeUtilityManager>(context); }); }); }); var container = builder.Build(); _busControl = container.Resolve<IBusControl>(); // 原有日志逻辑保留 source.TraceInformation("Start service..."); _busControl.Start(); source.TraceInformation("All services Started!"); foreach(SettingsProperty item in Properties.Settings.Default.Properties) { source.TraceInformation("Service SIP... " + item.Name + " : " + item.DefaultValue); } } // 配套的服务停止方法,对应原来的ServiceHost.Close public void StopService() { _busControl?.Stop(); }
关键注意事项
- 需提前安装对应NuGet包:
MassTransit.Autofac、MassTransit.RabbitMQ(使用其他传输替换为对应的包即可) - 接收端点的队列名称需要和客户端调用时指定的队列名保持一致,等价于原来WCF的服务地址
- 不要在
StartService方法内用局部变量存储IBusControl实例,方法执行完成后局部变量会被GC回收,导致服务自动停止 - 如果是开发测试场景不需要部署RabbitMQ,可以把
UsingRabbitMq替换为UsingInMemory,使用内存传输做测试 - 如果项目中已经有全局Autofac容器,不要新建
ContainerBuilder,直接在原有容器的注册逻辑里添加MassTransit的配置即可,避免服务注册隔离
内容的提问来源于stack exchange,提问作者CoolLife
相关产品推荐
相关产品推荐

