我想知道自己是否做错了什么,我希望MassTransit会自动在ReceiveEndpoints
中注册EndpointConvention
。
示例代码:
services.AddMassTransit(x =>
{
x.AddServiceBusMessageScheduler();
x.AddConsumersFromNamespaceContaining<MyNamespace.MyRequestConsumer>();
x.UsingAzureServiceBus((context, cfg) =>
{
// Load the connection string from the configuration.
cfg.Host(context.GetRequiredService<IConfiguration>().GetValue<string>("ServiceBus:ConnectionString"));
cfg.UseServiceBusMessageScheduler();
// Without this line I'm getting an error complaining about no endpoint convention for x could be found.
EndpointConvention.Map<MyRequest>(new Uri("queue:queue-name"));
cfg.ReceiveEndpoint("queue-name", e =>
{
e.MaxConcurrentCalls = 1;
e.ConfigureConsumer<MyRequestConsumer>(context);
});
cfg.ConfigureEndpoints(context);
});
});
我以为无需指定队列名称就无需发送此行EndpointConvention.Map<MyRequest>(new Uri("queue:queue-name"));
到总线,还是我错过了什么?
await bus.Send<MyRequest>(new { ...});
答案 0 :(得分:6)
EndpointConvention
是一种便捷的方法,它允许使用 Send 而不指定端点地址。 MassTransit中没有任何东西可以自动配置它,因为坦率地说,我不使用它。而且我也不认为其他人也应该。也就是说,人们出于任何原因都会使用它。
首先,考虑一下后果-如果每种消息类型都注册为端点约定,那么在多个端点上发布和使用的消息又如何呢?那是行不通的。
因此,如果您要按消息类型路由消息,MassTransit具有此功能。它叫做Publish
,效果很好。
但是,等等,这是一条命令,命令应该已发送。
这是事实,但是,如果您控制应用程序,并且知道代码库中只有一个使用方消耗KickTheTiresAndLightTheFires
消息约定,那么发布与发送一样好,而您不这样做不需要知道地址!
好的,这是详细信息。使用ConfigureEndpoints()时,MassTransit使用IEndpointNameFormatter
根据通过AddConsumer
,AddSagaStateMachine
等注册的类型来生成接收端点队列名称,并且可以使用相同的接口进行注册如果您想使用发送而不指定目标地址,则使用自己的端点约定。
您当然可以将消费者和消息类型的知识结合起来,但这就是您的要求。您已经在处理魔术(通过使用没有明确目的地的发送),为什么不正确呢?
string queueName = formatter.Consumer<T>()
使用该字符串将该消费者中的消息类型用作$"queue:{queueName}"
地址,并将其注册到EndpointConvention。
或者,您只需使用Publish
。