Rabbitmq 通过MassTransit请求/响应对话扩展订户

Rabbitmq 通过MassTransit请求/响应对话扩展订户,rabbitmq,masstransit,Rabbitmq,Masstransit,我使用Masstransit/RabbitMq实现了一个企业服务总线,用于web项目。我使用Masstransit模式在MQ上执行RPC 我正在总线中创建多个ReceiveEndpoint,该总线处理不同类型的消息。ESB还使用一个自定义配置文件来创建多个总线,因此我可以以某种方式在逻辑上实现Qos,甚至在单独的服务器上通过网络分发用户,以或多或少地提高性能 最近我在我的一个消费者身上看到了阻塞。如果我向一个长时间运行的消费者发送一些消息,每个消息大约需要5秒钟的时间,这看起来像是一个线程响应了

我使用Masstransit/RabbitMq实现了一个企业服务总线,用于web项目。我使用Masstransit模式在MQ上执行RPC

我正在总线中创建多个ReceiveEndpoint,该总线处理不同类型的消息。ESB还使用一个自定义配置文件来创建多个总线,因此我可以以某种方式在逻辑上实现Qos,甚至在单独的服务器上通过网络分发用户,以或多或少地提高性能

最近我在我的一个消费者身上看到了阻塞。如果我向一个长时间运行的消费者发送一些消息,每个消息大约需要5秒钟的时间,这看起来像是一个线程响应了我的请求,同时发送的消息等待前面的消息被消费

到目前为止,我将UseConcurrencyLimit64设置为零,尝试将预取计数增加到50,但RabbitMq在队列详细信息中显示为0

为什么消费者一次只处理一条消息

MassTransit v3.5.7

编辑:我后来找到了。在我看来,这是同样的问题

更新与Chris的示例不同的地方,我使用RabbitMq并使用反射创建使用者,这样我就可以使用配置文件管理ESB。RabbitMq管理控制台上仍在执行预取计数0

var busControl = Bus.Factory.CreateUsingRabbitMq(x =>
        {
            x.UseConcurrencyLimit(64);
            IRabbitMqHost host = x.Host(new Uri(Config.host), h =>
            {
                h.Username("userName");
                h.Password("password");
            });

            var obj = Activator.CreateInstance([SomeExistingType]);

            x.ReceiveEndpoint(host, "queueName", e =>
            {
                e.PrefetchCount = 64;//config.prefetchCount;
                e.PurgeOnStartup = true;
                if (config.retryCount > 0)
                {
                    e.UseRetry(retry => retry.Interval(config.retryCount, config.retryInterval));
                }
                e.SetQueueArgument("x-expires", config.timeout * 1000 /*Seconds to milliseconds*/);
                e.SetQueueArgument("temporary", config.temporary);

                e.Consumer(consumer, f => obj);

            }); 

        })
busControl.StartAsync

在我将预回迁计数设置为1时更新2,以让MassTransit处理工作负载,因为我有多个客户服务器和一个RabbitMq集群。但是,当我向使所有线程都处于繁忙状态的队列发送许多消息时,新请求等待在发送方队列中被空闲线程接收。我增加了预取计数,这样我就可以为新请求提供更多的空闲线程。按照Chris的建议,我在配置接收端点时设置预取计数。谢谢Chris确认后,我会立即将Chris回复标记为答案。

如果您在RabbitMQ控制台中看到预回迁计数为0,则可能是在错误的位置配置了它。你应该有以下几点:

cfg.ReceiveEndpoint("my-queue", x =>
{
    x.PrefetchCount = 64;
    x.Consumer<MyConsumer>();
});
这将把接收端点使用者配置为64的预取计数,该计数应显示在RabbitMQ管理控制台上的使用者中


另一方面,如果您的消费者使用诸如thread.Sleep之类的东西阻塞线程,我已经看到过这样的情况,它会限制线程池的并发性

谢谢你的回答。我已经更新了我的原始问题,请检查我是否遗漏了什么?另一个更新:eventhough RabbitMq显示预回迁计数为0,但实际上不是0。我可以说在做了一些测试之后。你的回答看起来对我很有用,我会解释我在最初的问题中犯了什么错。请确认……在您的示例中,所有消息都使用单个消费者。通常不是最佳选择,但如果您坚持使用它,请确保您的使用者没有任何实例变量,因为它们将由所有并发消息共享。您可以通过将Activator.CreateInstance调用移动到e.consumer调用的lambda方法中来解决此问题。@ChrisPatterson非常感谢,我以前从你的回答中读到了那个批评家。在这个例子中,我觉得我需要修改这个方法,使之对于这个特定的问题更加简单化。实际上,我为每种消息类型创建了许多ReceiveEndpoint。此外,我创建了几个总线来将一些消息分组在一起,因为其中一些总线使用请求/响应模式,而其他总线用于发布/订阅。