我正在阅读.NET API Guide这是非常好的信息,但我对RabbitMQ如何管理线程感到有点困惑。在并发注意事项部分下,它指出每个IConnection都由一个后台线程备份。然后继续:
应用程序可以看到线程模型的性质的一个地方是应用程序向库注册的任何回调。这些回调包括:
- 任何IBasicConsumer方法
- IModel上的BasicReturn事件
- IConnection,IModel等上的任何各种关闭事件。
我有点困惑。它们是否意味着每次调用HandleBasicDeliver
时都会创建一个新线程?在这种情况下,收到消息的线程数量会一样多,而且并发性由预取计数和消费者数量控制吗?
因此,如果我们考虑一个案例,我有一个一个 IConnection
和两个频道(IModel
),预取数量为一个每个频道和一个 EventingBasicConsumer
,我们在应用中运行了多少线程?
答案 0 :(得分:0)
我已经修改了我的答案和研究,你确实看起来不错。
我使用Rabbitmq创建了一个应用程序,并且我遇到了一种情况,我必须为IModel(通道)的数量共享相同的IConnection(连接)。这就是我们应该使用一个连接的方式,因为一个连接足以为多个通道提供服务。
我遇到的问题是,如果我为每个客户端创建一个连接,那么该队列的连接数会不断增加,这会导致应用程序在一段时间后终止。
所以除非需要,否则我们应该避免多个连接。如果可能,只有一个连接应用于多个通道。
即使IConnection关闭,IModel仍然存在。但是如果IConnection关闭,那么该连接下的所有IModel都将被关闭。
答案 1 :(得分:0)
自从我第一次提出这个问题以来,我已经对这个主题进行了大量的研究,所以我想我会在这里发帖,以防有人发现这些信息有用。
带上一粒盐。这些是我对兔子(C#)如何运作的理解。
IConnection是一个实际的套接字连接。它将有一个线程轮询它。根据我读过的建议,每个应用程序使用一个连接,除非你有理由使用更多。
在C#中,通道不被认为是线程安全的,因此每个线程都有一个通道并不是一个坏主意,否则应该确保使用锁定机制。 https://www.rabbitmq.com/dotnet-api-guide.html
根据我对阅读源代码的理解,handleBasicDeliver(我认为所有IModel调用)都在一个Task中运行。考虑到这一点,拥有多个消费者确实增加了软件的并发性,因为如果一个消费者收到消息并且正在忙着处理它,另一个消费者可以自由地接收消息并在另一个线程中执行它。此外,每个消费者必须在其自己的频道上以最大化并发性,否则保留消息顺序。但是,如果不欢迎这种并发性,请考虑使用单个通道来确保按照它们到达的顺序处理消息。 注意:第3点可能已更改,因为不再保留通道顺序。我没有时间去探索新的变化,所以请仔细阅读并得出自己的结论: https://github.com/rabbitmq/rabbitmq-dotnet-client/issues/251