使用交换和使用 MassTransit 的路由密钥发布消息
Posted
技术标签:
【中文标题】使用交换和使用 MassTransit 的路由密钥发布消息【英文标题】:Publish message using exchange and routing key using MassTransit 【发布时间】:2015-07-20 17:59:49 【问题描述】:我已经关注 MassTransit 几个星期了,我很好奇其中的可能性。但是,我似乎无法完全正确地理解这些概念。
预期行为 我想将消息发布到带有路由键的“直接”交换,该路由键绑定到两个不同的队列以执行其他活动。
当我尝试使用 MassTransit 实现相同的逻辑以获得更好的可扩展性时。我发现 MassTransit 基于具有扇出类型的队列名称创建自己的交换。
通过交换和路由键发布消息的经典代码
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
channel.ExchangeDeclare(exchange, "direct");
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange, routingKey, null, body);
Console.WriteLine(" [x] Sent 0", message);
有没有办法在 MassTransit 中使用 routingkey 配置直接或主题交换?
【问题讨论】:
【参考方案1】:这不是 MassTransit 支持的方案。 MassTransit 将始终创建一个扇出队列。如果您自己管理拓扑,则可以使用IEndpoint.Send
直接将消息发送到您创建的交换。在这种情况下,你放弃了很多 MT 提供的东西。
我也不确定在这种情况下“更好的可扩展性”是什么意思。扇出交换的性能优于直接交换(在大多数情况下),因为不需要处理路由逻辑。
如果您在 MassTransit mailing list 上澄清了您对性能的担忧,也许我们可以为您提供更多帮助。
【讨论】:
感谢您的 cmets,我的流程需要多个发布者并行发布消息,因此考虑了“直接”或“主题”交换,但 MassTransit 不支持它们。您对处理此问题的最佳方法有任何建议,还是您更喜欢在此过程中使用多个队列。另外,如果您指导我了解 MassTransit 的架构,那将会很有帮助。 我不太确定您要做什么。并行发布消息对我来说真的没有意义。使用 MT 3.0,您可以进行异步发布。不过,一切都或多或少与消息传递并行。如果一个线程正在发布,那么另一个线程也可以。与消费相同。 基本上,忘记 RMQ 中的拓扑结构,只需定义类型(最好是接口)的消息契约,让 MT 为您将它们绑定在一起。【参考方案2】:下面的代码做同样的工作,但有一个额外的扇出交换:
TestMessage(直接交换)-> TestMessage_Queue(扇出交换)-> TestMessage_Queue(队列)
var bus = Bus.Factory.CreateUsingRabbitMq(cfg =>
var host = cfg.Host(new Uri("rabbitmq://localhost"), h =>
h.Username("guest");
h.Password("guest");
);
cfg.Send<TestMessage>(x => x.UseRoutingKeyFormatter(context => "routingKey"); );
cfg.Message<TestMessage>(x => x.SetEntityName("TestMessage"));
cfg.Publish<TestMessage>(x => x.ExchangeType = ExchangeType.Direct; );
cfg.ReceiveEndpoint(host, "TestMessage_Queue", e =>
e.BindMessageExchanges = false;
e.Consumer<UpdateCustomerConsumer>();
e.Bind("TestMessage", x =>
x.ExchangeType = ExchangeType.Direct;
x.RoutingKey = "routingKey";
);
);
);
bus.Start();
【讨论】:
那是哪个版本?版本 5.5.1 没有 SendMassTransit 不使用主题交换来处理发布和订阅,而是为正在发布的消息类型创建交换,并将这些交换绑定到消费者队列。
RabbitMQ 的路由密钥方法效率较低,它更喜欢使用交换结构来简化消息路由(无需维护哈希表)。
无需处理交换和路由键,只需定义您的命令和/或事件类型,发送或发布这些消息并让消费者完成他们的工作。
【讨论】:
创建额外的类型,虽然非常干净,但可能很乏味。一种诱人的方法是,您的总线甚至不知道交换了哪些确切类型,因为您将所有内容包装在通用的“类似包装器”类型中(可能会丢失静态类型,因为只有单个包装器类型)。然而,单一包装器类型的一个缺点是,从技术上讲,从单一交换到所有订阅者都有一个风扇,因此所有订阅者都检索所有消息,过滤必须在内部完成,在处理程序中。 这是路由键方法变得方便的地方。通过为每个包装的消息和映射到队列的路由键设置一个显式键,您可以以精确的方式控制订阅。幸运的是,正如@jan-mucinsky 在另一个答案中提到的那样,这似乎在 MT 中有效。我并不是在提倡这种模式,我只是说这在技术上是可行的,并且有其背后的理由。 @WiktorZychla 你知道如何实现吗? @Aranha:是的,dropped a blog entry note on that以上是关于使用交换和使用 MassTransit 的路由密钥发布消息的主要内容,如果未能解决你的问题,请参考以下文章
MassTransit - 如何创建具有通用类型和 2 个不同消费者的交换主题
未在代码中指定的交换上的MassTransit ACCESS_REFUSED
路由与交换技术在路由器r1和r2中设置enable密文密钥net?