我们刚开始使用RabbitMQ和C#。我目前的计划是在数据库中配置在给定服务器上运行的消费者的数量和种类。我们有一个现有的Windows服务,当它开始时,我想生成所有RabbitMQ消费者。我的问题是从Windows服务中提取这些内容的最佳方法是什么?
我目前的计划是从数据库中读取配置并为每个使用者生成一个长时间运行的任务。
var t = new Task(() =>
{
var instance = LoadConsumerClass(consumerEnum, consumerName);
instance.StartConsuming();//blocking call
}, TaskCreationOptions.LongRunning);
t.Start();
这比为每个消费者创建一个线程更好还是更差?
var messageConsumer = LoadConsumerClass(consumerEnum, consumerName);
var thread = new Thread(messageConsumer.StartConsuming);
我希望不止一些人已经尝试过我正在做的事情,并且可以为我提供一些有关哪些方面运作良好,哪些方面没有效果的想法。
答案 0 :(得分:0)
在EasyNetQ中,我们为单个连接上的所有消费者提供了一个调度程序线程。我们还提供了一个从消息处理程序返回Task的工具,因此如果要进行数据库调用,转到文件系统或发出Web服务请求,可以很容易地执行异步IO。
说过让每个消费者在不同的线程上消费是完全合法的。我想这取决于您的消息吞吐量,您拥有的消费者数量以及消息处理程序的性质。
答案 1 :(得分:0)
我坚持使用Tasks,因为它们为您提供了更多功能,并且通常允许更少的样板代码。 并且,如果我正确理解您的代码,您将在第二种情况下共享一个频道(IModel)。这可能会导致麻烦,因为默认的IModel实现不是线程安全的(或曾经是)。关于线程安全的细微差别你需要注意。 但这取决于您的使用模式。如果您不希望每个消费者都有多条消息/秒,或者您的应用程序可以快速处理消息,那么对于所有消费者而言,单个线程可能是您的最佳选择。
答案 2 :(得分:0)
任务很棒,但你不会真正使用它可以做的所有事情。你唯一需要的是并行工作。 几个月前,我遇到了同样的问题,我完成的是 - 每个计算类型(每个队列)的一个线程,它在消息到达时阻塞,并且在等待消息时不消耗cpu。 为每个线程打开一个新通道。 至于连接 - 如果你的应用程序是为了处理高负载的消息,我建议你为每个X工作者打开连接(想你的X),因为只有一个通道可以通过连接发送消息,所以假设一个工作者是消耗大量消息,其他消息在连接级别被阻止等待它自由。