【问题标题】:What is the overhead of Masstransit when running on RabbitMQ?在 RabbitMQ 上运行时,Masstransit 的开销是多少?
【发布时间】:2019-04-24 21:15:16
【问题描述】:

将 Masstransit 与 RabbitMQ 结合使用时,我看到了令人失望的性能。交付/获取下降到 0.20/秒。我开始用一个简单的测试应用程序来研究这个问题。此应用程序并行运行一个使用 RabbitMQ 客户端库向 RabbitMQ 发送消息的线程和一个使用 Masstransit 库向 RabbitMQ 发送相同消息的线程。 RabbitMQ 客户端库可以发送比 Masstransit 库多 10 倍的消息。

RabbitMQ 在 HyperV 机器的 Docker 容器中运行。 Masstransit 的 PublishConfirm 标志有一些影响,但影响不大。 为了获得公平的比较,为 RabbitMQ 案例定义了与 Masstransit 案例中使用的相同的拓扑。

公共交通代码:

        public MasstransitMessageSender(string user, string password, string rabbitMqHost)
        {
            this.user = user;
            this.password = password;
            this.rabbitMqHost = rabbitMqHost;
        }

        public RabbitMqMessageSender(string user, string password, string rabbitMqHost)
        {
            var myUri = new Uri(rabbitMqHost);

            this.factory = new ConnectionFactory
            {
                HostName = myUri.Host,
                UserName = user,
                Password = password,
                VirtualHost = myUri.LocalPath,
                Port = (myUri.Port > 0 ? myUri.Port : -1),
                AutomaticRecoveryEnabled = true
            };
        }

        public Task SendCommands(int numberOfMessages)
        {
            return Task.Run(() =>
            {
                var busControl = global::MassTransit.Bus.Factory.CreateUsingRabbitMq(
                    sbc =>
                    {
                        // Host control
                        var host =
                            sbc.Host(
                                new Uri(this.rabbitMqHost),
                                h =>
                                {
                                    h.Username(this.user);
                                    h.Password(this.password);
                                    h.Heartbeat(60);
                                    h.PublisherConfirmation = false;
                                });
                    });

                busControl.StartAsync().Wait();
                var task = busControl.GetSendEndpoint(new Uri(this.rabbitMqHost + "/MasstransitService"));
                var tasks = new List<Task>();

                task.Wait();
                var endpoint = task.Result;
                for (var i = 0; i < numberOfMessages; i++)
                {
                    tasks.Add(endpoint.Send<IMyMessage>(new
                    {
                        Number = i,
                        Description = "MyMessage"
                    }));
                }

                Task.WaitAll(tasks.ToArray());
            });
        }

RabbitMQ 代码:

        public RabbitMqMessageSender(string user, string password, string rabbitMqHost)
        {
            var myUri = new Uri(rabbitMqHost);

            this.factory = new ConnectionFactory
            {
                HostName = myUri.Host,
                UserName = user,
                Password = password,
                VirtualHost = myUri.LocalPath,
                Port = (myUri.Port > 0 ? myUri.Port : -1),
                AutomaticRecoveryEnabled = true
            };
        }

        public Task SendCommands(int numberOfMessages)
        {
            return Task.Run(() =>
            {
                using (var connection = this.factory.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        var messageProperties = channel.CreateBasicProperties();
                        channel.ExchangeDeclare("PerformanceConsole:ShowRabbitMqMessage", "fanout", true, false, null);
                        channel.ExchangeDeclare("RabbitMqService", "fanout", true, false, null);
                        channel.QueueDeclare("RabbitMqService", true, false, false, null);
                        channel.ExchangeBind("RabbitMqService", "PerformanceConsole:ShowRabbitMqMessage", "", null);
                        channel.QueueBind("RabbitMqService", "RabbitMqService", "", null);
                        for (var i = 0; i < numberOfMessages; i++)
                        {
                            var bericht = new
                            {
                                Volgnummer = 1,
                                Tekst = "Bericht"
                            };
                            var body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(bericht));
                                channel.BasicPublish("RabbitMqService", "", messageProperties, body);
                        }
                    }
                }
            });
        }

RabbitMQ 仪表板显示以下费率:

Masstransit 传入 664 msg/s RabbitMQ 传入 6764 msg/s

我希望收到的费率在同一范围内。

可能是我配置有误,欢迎提出建议。

【问题讨论】:

  • 您可以使用基准工具进行更好的吞吐量测试:github.com/MassTransit/MassTransit-Benchmark - 增加客户端、预取和计数,您应该可以轻松获得可比较的性能。
  • 您也没有使用 await 和其他异步构造,Task.WaitAll() 在 TPL 中表现不佳。

标签: performance rabbitmq masstransit


【解决方案1】:

使用 MassTransit-Benchmark,我在 MacBook Pro 2015 上获得以下性能,在 OS X 上使用 netcoreapp2.2。

PhatBoyG-Pro15:MassTransit-Benchmark Chris$ dotnet run -f netcoreapp2.2 -- --clients=50 --count=50000 --prefetch=100
MassTransit Benchmark

Transport: RabbitMQ
Host: localhost
Virtual Host: /
Username: guest
Password: *****
Heartbeat: 0
Publisher Confirmation: False
Running Message Latency Benchmark
Message Count: 50000
Clients: 50
Durable: False
Payload Length: 0
Prefetch Count: 100
Concurrency Limit: 0
Total send duration: 0:00:05.2250045
Send message rate: 9569.37 (msg/s)
Total consume duration: 0:00:07.2385114
Consume message rate: 6907.50 (msg/s)
Concurrent Consumer Count: 8
Avg Ack Time: 4ms
Min Ack Time: 0ms
Max Ack Time: 251ms
Med Ack Time: 4ms
95t Ack Time: 6ms
Avg Consume Time: 1431ms
Min Consume Time: 268ms
Max Consume Time: 2075ms
Med Consume Time: 1639ms
95t Consume Time: 2070ms

您可以下载基准测试并自行运行: https://github.com/MassTransit/MassTransit-Benchmark

【讨论】:

  • 我曾经使用基准测试工具来改进我的代码。但我认为我的问题是 a 正在使用 Visual Studio ide 运行我的性能工具。在调试模式下运行代码会使 RabbitMQ 客户端库慢 20%,但 Masstransit 库会慢 575%。这是使用TPL造成的吗?
  • 我不知道,我从来没有在调试模式下测试过性能,也没有使用过 Visual Studio。
  • 我通过添加重试机制更改了接收端点配置:configurator.UseMessageRetry(r => r.Incremental(3, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10)));在消费者中抛出随机异常。任务 IReportConsumerMetric.Consumed(Guid messageId) { if (rnd.Next(100)
  • 这将需要使用重新传递,这会将消息重新排队。您的重试延迟比应该使用的要长,tbh。
猜你喜欢
  • 1970-01-01
  • 2021-12-12
  • 2021-07-26
  • 1970-01-01
  • 2013-12-19
  • 2014-02-14
  • 2010-11-29
  • 1970-01-01
  • 2011-11-23
相关资源
最近更新 更多