消费者离线时将消息保留在队列中

时间:2017-08-02 11:57:26

标签: rabbitmq masstransit

我在C#项目中使用Masstransit。

我有一个发布商和消费者服务,当他们两个都出现时,就没有问题了。但如果消费者离线,则发布的消息不会进入队列。他们就会消失。

预期的行为是将消息保留在队列中,直到消费者启动,然后将其发送给它。我在谷歌小组中发现了几个有相同问题的主题,但我不清楚如何解决这个问题。

我觉得这个功能并不是开箱即用的,因为根据我的理解,这是RabbitMQ和MT的主要目的。

我创建发布者总线的方式:

public static IBusControl CreateBus()
{
    return Bus.Factory.CreateUsingRabbitMq(sbc =>
    {
        var host = sbc.Host(new Uri("rabbitmq://RMQ-TEST"), h =>
        {
            h.Username("test");
            h.Password("test");
        });
        sbc.ReceiveEndpoint(host, "test_queue", ep =>
        {
            ep.Handler<IProductDescriptionChangedEvent>(
                content => content.CompleteTask);
        });
    });
}

消费者:

    public static void StartRmqBus()
    {
        var bus = Bus.Factory.CreateUsingRabbitMq(cfg =>
        {
            var host = cfg.Host(new Uri("rabbitmq://RMQ-TEST"), h =>
            {
                h.Username("test");
                h.Password("test");
            });

            cfg.ReceiveEndpoint(host, "test_queue", ep =>
            {
                ep.Consumer<ProductChangedConsumer>();
            });
        });

        bus.Start();
    }

修改

这是一个更有趣的功能:如果我停止两个服务并通过MT的管理界面手动将消息发送到队列,则消息在test_queue中等待。但是当我启动发布者或消费者服务时,它会落到test_queue_error队列。

2 个答案:

答案 0 :(得分:1)

对于已发布和使用者,您使用相同的队列,并且发布者拥有此消息类型的使用者,正如您在自己的答案中所指出的那样。

如果您的发布商不使用消息,最好从中删除接收端点,然后您的服务将是仅发送的。

如果您有多个服务,其中每个服务都需要为相同的消息类型拥有自己的使用者 - 这就是pub-sub的工作方式,而必须每个服务具有不同的队列。这在文档的Common Gotchas部分中进行了描述。在这种情况下,每个服务都将获得它自己的已发布消息的副本。

如果您有一个队列 - 您将获得竞争消费者,并且此方案仅对水平可伸缩性有效,其中您运行相同服务的多个实例以在处理过慢时增加已处理消息的数量。在这种情况下,所有这些实例都将使用来自同一队列的消息。在这种情况下,只有一个实例会收到消息。

答案 1 :(得分:0)

好像我的发布商设置不正确。删除此部分后:

sbc.ReceiveEndpoint(host, "test_queue", ep =>
{
    ep.Handler<IProductDescriptionChangedEvent>(
        content => content.CompleteTask);
});

它开始按预期工作。看起来它消耗了自己的消息,这就是为什么当消费者关闭时我没有看到队列中的消息。