在RabbitMQ中,池化连接和通道之间是否存在性能差异?

64

我是一个Rabbitmq的新手(也是程序开发方面的),如果我的提问很显而易见,那么请提前原谅。我正在创建一个在队列中工作的线程之间共享的池,但我不确定在池中应该使用连接还是通道。

我知道需要使用通道来执行实际的工作,但是每个连接是否有一个通道会带来性能上的优势(对于从队列中获取更多吞吐量)?或者我最好只在应用程序中使用一个单独的连接并池化许多通道?

注:因为我正在池化资源,所以初始成本不是问题,因为我知道连接比通道更昂贵。 我更加关心的是吞吐量。

3个回答

91
我在rabbitmq网站上发现了这篇文章,它位于底部,所以我引用了下面相关的部分。 简而言之,每个应用程序应该有1个连接,每个线程应该有1个通道。
连接 AMQP连接通常是长期的。 AMQP是一个应用级协议,使用TCP进行可靠的传递。 AMQP连接使用身份验证,并且可以使用TLS(SSL)进行保护。当应用程序不再需要连接到AMQP代理时,应优雅地关闭AMQP连接,而不是突然关闭底层TCP连接。
通道 一些应用程序需要与AMQP代理建立多个连接。但是,同时保持许多TCP连接处于打开状态是不可取的,因为这样会消耗系统资源并使防火墙配置更加困难。 AMQP 0-9-1连接被复用为可以考虑为“共享单个TCP连接的轻量级连接”的通道。
对于使用多个线程/进程进行处理的应用程序,非常常见的是每个线程/进程打开一个新的通道,而不是在它们之间共享通道。
特定通道上的通信完全与另一个通道上的通信分离,因此每个AMQP方法也都带有一个通道号,客户端使用该号码来确定方法为哪个通道(因此,例如需要调用哪个事件处理程序)。
建议每个线程有1个通道,即使它们是线程安全的,因此您可以通过一个通道发送多个线程。就您的应用程序而言,我建议您每个线程只使用1个通道。
此外,建议每个通道只有1个消费者。
这些仅是指南,因此您将不得不进行一些测试以查看哪种方式最适合您。

这个主题在这里这里提供了一些见解。

尽管所有的指导原则这篇文章都建议,使用多个连接很可能不会影响性能。但并没有具体说明是讨论客户端还是服务器(rabbitmq)端。一个要点是,使用更多的连接当然会消耗更多的系统资源,如果这不成问题,并且希望拥有更高的吞吐量,则使用多个连接可能会更好,如这篇文章所示,多个连接将允许您获得更高的吞吐量。原因似乎是即使存在多个通道,在同一时间只有一个消息通过连接。因此,大型消息将阻塞整个连接,或者许多不重要的消息在同一连接但不同通道上阻塞重要消息。再次强调资源是一个问题。如果您正在使用单个连接使用所有带宽,则添加额外的连接不会比在单个连接上具有两个通道的性能提高。此外,每个连接都将使用更多内存、CPU和文件句柄,但这可能不是一个问题,尽管在扩展时可能会成为一个问题。


2
根据API文档,Channel实例可供多个线程安全使用。对Channel的请求进行序列化处理,每次只有一个线程能够在Channel上运行命令。即便如此,应用程序应该优先使用每个线程一个Channel而不是在多个线程之间共享同一个Channel。 - djechlin
1
好的,已编辑。我写那个有点奇怪,文档可能改变了吗?不太可能。只是我的错误,抱歉。但建议仍然是一样的。一个消费者,一个通道,一个线程。 - robthewolf
6
通道是否线程安全取决于实现方式。Java 实现是安全的,而 .NET 实现则不是。请参见 https://dev59.com/LW025IYBdhLWcg3w_rFA#17829906。 - Evgeniy Berezovsky

15

除了被接受的答案之外:

如果您拥有一组RabbitMQ节点,其中有一个负载均衡器或短暂的DNS(使得每次连接到不同的rabbit节点成为可能),那么单个长时间连接意味着一个应用程序节点专门与一个RabbitMQ节点配合工作。这可能导致一个RabbitMQ节点比其他节点更加繁忙。

上面提到的另一个问题是发布和消费是阻塞操作,这会导致消息排队。使用更多的连接将确保1.每条消息的处理时间不会阻塞其他消息2.大型消息不会阻塞其他消息。

这就是为什么值得考虑使用小的连接池(请记住上面提出的资源问题)


3
你所建议的这个小型连接池,是由提供方提供的还是我需要自己实现呢? - Mahdi

1
“一个线程一个通道”的做法可能是安全的(我说可能,因为我没有自己进行过任何研究,并且我没有理由怀疑文档 :)),但请注意这里有一种情况会导致其失效:
如果您使用带有 RabbitMQ 的 RPC 直接回复,那么您不能重复使用相同的通道来消费另一个 RPC 请求。我在google 用户组中询问了有关此问题的详细信息,而我从迈克尔·克利欣(他似乎积极参与 RabbitMQ 的开发)那里得到的答案是:

无论如何,直接回复都不应该与通道共享一起使用。

我已经通过电子邮件向 Pivotal 发送了更新其文档以解释 amq.rabbitmq.reply-to 如何在后台工作的请求,但我仍在等待回复(或更新)。
因此,如果您想坚持“一个线程一个通道”,请注意,这将无法与“直接回复”很好地配合使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接