简体   繁体   English

创建许多消费者的RabbitMQ最佳实践

[英]RabbitMQ best practice for creating many consumers

We are just starting to use RabbitMQ with C#. 我们才刚刚开始将RabbitMQ与C#结合使用。 My current plan is to configure in the database the number and kind of consumers to run on a given server. 我目前的计划是在数据库中配置要在给定服务器上运行的使用者的数量和种类。 We have an existing windows service and when that starts I want to spawn all of the RabbitMQ consumers. 我们有一个现有的Windows服务,当它启动时,我想生成所有RabbitMQ使用者。 My question is what is the best way to spwan these from a windows service? 我的问题是从Windows服务中获取这些的最佳方法是什么?

My current plan is to read the configuration out of the database and spawn a long running task for each consumer. 我当前的计划是从数据库中读取配置,并为每个使用者生成一个长期运行的任务。

                var t = new Task(() =>
                {
                    var instance = LoadConsumerClass(consumerEnum, consumerName);
                    instance.StartConsuming();//blocking call
                }, TaskCreationOptions.LongRunning);
                t.Start();

Is this better or worse than creating a thread for each consumer? 这比为每个使用者创建线程更好还是更坏?

                var messageConsumer = LoadConsumerClass(consumerEnum, consumerName);
                var thread = new Thread(messageConsumer.StartConsuming);

I'm hoping that more than a few others have already tried what I'm doing and can provide me with some ideas for what worked well and what didn't. 我希望有更多的人已经尝试过我正在做的事情,并且可以为我提供一些有关什么有效和无效的想法。

In EasyNetQ we have a single dispatcher thread for all consumers on a single connection. EasyNetQ中,我们为单个连接上的所有使用者提供了一个调度程序线程。 We also provide a facility to to return a Task from the message handler, so it's easy to do async IO if you want to make a database call, go to the file system, or make a web service request. 我们还提供了一种从消息处理程序返回Task的功能,因此,如果要进行数据库调用,转到文件系统或进行Web服务请求,则很容易执行异步IO。

Having said that it's perfectly legitimate to have each consumer consuming on a different thread. 话虽如此,让每个消费者在不同的线程上消费是完全合法的。 I guess it depends on your message throughput, how many consumers you have and the nature of your message handlers. 我想这取决于您的消息吞吐量,拥有多少使用者以及消息处理程序的性质。

I'd stick with Tasks as they give you more features and generally allow for less boilerplate code. 我坚持使用Tasks,因为它们为您提供了更多功能,并且通常减少了样板代码。 And, If I understand your code correctly, you'd be sharing a channel (IModel) in second case. 而且,如果我正确理解您的代码,则在第二种情况下,您将共享一个频道(IModel)。 This might cause troubles as the default IModel implementation is not thread safe (or used to be). 这可能会引起麻烦,因为默认的IModel实现不是线程安全的(或者曾经是)。 There're more subtle nuances regarding thread safety you'd have to watch out. 关于线程安全性,您还需要注意一些细微的差别。 But it depends on your usage patterns. 但这取决于您的使用模式。 If you don't expect many messages/sec on each consumer, or if your app can handle messages fast then perhaps a single thread for all consumers will be you best option. 如果您不希望每个使用方每秒收到很多消息,或者您的应用程序可以快速处理消息,那么最好为所有使用方使用单个线程是最好的选择。

Task is great, but you not really going to use all the stuff it can do. 任务很棒,但是您不会真正使用它可以做的所有事情。 The only thing you need is to do work in parallel. 您唯一需要做的就是并行工作。 I faced the same question couple of months ago, what I finished with - is a thread per computation type (per queue) which is blocking on message arrival and doesn't consume cpu when waiting for messages. 几个月前,我遇到了同样的问题,我完成的任务是-每个计算类型(每个队列)一个线程,该线程在消息到达时阻塞,并且在等待消息时不占用cpu。 Open a new channel for each one of the threads. 为每个线程打开一个新通道。 As for connections - if you application is meant to deal with high load of messages, I suggest you opening connection for every X workers (figure you your X), since only one channel can send the messages through the connection, so assuming one worker is consuming large message the others are blocked on connection level waiting it to be free. 至于连接-如果您的应用程序旨在处理大量的消息,我建议您为每个X工作者打开连接(图X),因为只有一个通道可以通过该连接发送消息,因此假设一个工作者是消耗大量消息,其他消息在连接级别被阻止,以等待其释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM