【问题标题】:Publish message using exchange and routing key using MassTransit使用交换和使用 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 配置直接或主题交换?

【问题讨论】:

    标签: c# message-queue masstransit rabbitmq-exchange


    【解决方案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 没有 Send 或 Publish
    【解决方案3】:

    MassTransit 不使用主题交换来处理发布和订阅,而是为正在发布的消息类型创建交换,并将这些交换绑定到消费者队列。

    RabbitMQ 的路由密钥方法效率较低,它更喜欢使用交换结构来简化消息路由(无需维护哈希表)。

    无需处理交换和路由键,只需定义您的命令和/或事件类型,发送或发布这些消息并让消费者完成他们的工作。

    【讨论】:

    • 创建额外的类型,虽然非常干净,但可能很乏味。一种诱人的方法是,您的总线甚至不知道交换了哪些确切类型,因为您将所有内容包装在通用的“类似包装器”类型中(可能会丢失静态类型,因为只有单个包装器类型)。然而,单一包装器类型的一个缺点是,从技术上讲,从单一交换到所有订阅者都有一个风扇,因此所有订阅者都检索所有消息,过滤必须在内部完成,在处理程序中。
    • 这是路由键方法变得方便的地方。通过为每个包装的消息和映射到队列的路由键设置一个显式键,您可以以精确的方式控制订阅。幸运的是,正如@jan-mucinsky 在另一个答案中提到的那样,这似乎在 MT 中有效。我并不是在提倡这种模式,我只是说这在技术上是可行的,并且有其背后的理由。
    • @WiktorZychla 你知道如何实现吗?
    猜你喜欢
    • 2020-01-13
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多