【发布时间】:2020-06-21 21:31:42
【问题描述】:
我有这个设计选择问题,不知何故苦苦挣扎,但徒劳无功。它仅适用于特定场景。
我正在尝试在 MassTransit 中发布和使用消息。 例如:(Publisher - 一个简单的控制台应用)
IShape message = GetShape(/**Business Logic will return some concrete object (Circle or square) based on some business inputs**/);
bus.Publish(message);
(消费者 - CircleConsumer 和 SquareConsumer)
class CircleConsumer : IConsumer<IShape>
{
public Task Consume(ConsumeContext<IShape> context)
{
var circle = context.Message as Circle;
return Task.CompletedTask;
}
}
class SquareConsumer : IConsumer<IShape>
{
public Task Consume(ConsumeContext<IShape> context)
{
var square = context.Message as Square;
return Task.CompletedTask;
}
}
(.Net Core 托管服务项目中的消费者配置)
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>()
.AddScoped<SquareConsumer>()
.AddScoped<CircleConsumer>()
.AddMassTransit(cfg =>
{
cfg.AddBus(ConfigureBus);
cfg.AddConsumer<SquareConsumer>();
cfg.AddConsumer<CircleConsumer>();
})
.AddSingleton<IBus>(provider => provider.GetRequiredService<IBusControl>())
.AddSingleton<IHostedService, TestMTConsumerHostedService>();
IBusControl ConfigureBus(IServiceProvider provider)
{
return Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = cfg.Host(hostContext.Configuration["RabbmitMQ:Server:Host"], hostContext.Configuration["RabbmitMQ:Server:VirtualHost"], h =>
{
h.Username(hostContext.Configuration["RabbmitMQ:Auth:Username"]);
h.Password(hostContext.Configuration["RabbmitMQ:Auth:Password"]);
});
cfg.ReceiveEndpoint("CircleQueue", ep =>
{
ep.PrefetchCount = 16;
ep.UseMessageRetry(r => r.Interval(2, 100));
ep.Consumer<CircleConsumer>(provider);
});
cfg.ReceiveEndpoint("SquareQueue", ep =>
{
ep.PrefetchCount = 16;
ep.UseMessageRetry(r => r.Interval(2, 100));
ep.Consumer<SquareConsumer>(provider);
});
});
}
});
我的要求是让发布者在不了解具体类的情况下发布消息。并且只有一个消费者根据消息类型接收消息。
但看起来消费者都在接收消息并且投射也不起作用。 Desired:假设当发布者发送 Square 对象时,只有 Square 消费者应该收到调用。但是,就我而言,SquareConsumer 和 CircleConsumer 都收到了消息。
作为一种解决方法,这是可行的:
-
始终发布具体对象。
bus.Publish(new Square()); -
用具体类型声明消费者。
class CircleConsumer : IConsumer<Circle> { public Task Consume(ConsumeContext<Circle> context) { var circle = context.Message; return Task.CompletedTask; } } class SquareConsumer : IConsumer<Square> { public Task Consume(ConsumeContext<Square> context) { var square = context.Message; return Task.CompletedTask; } }
但是,如果我能通用地做到这一点,那就太好了。
有什么建议吗?
【问题讨论】: