RabbitMQ和通道与连接的关系

RabbitMQ Java客户端具有以下概念:

  • Connection - 与RabbitMQ服务器实例的连接
  • Channel - ???
  • 消费者线程池 - 消耗RabbitMQ服务器队列消息的线程池
  • 队列 - 按FIFO顺序保存消息的结构
  • 我试图理解这种关系, 更重要的是 ,他们之间的关系。

  • 我还不太确定Channel是什么,除了这是您发布和使用的结构,并且它是从一个开放连接创建的。 如果有人能向我解释“频道”代表什么,它可能有助于清除一些事情。
  • Channel和Queue之间的关系是什么? 是否可以使用同一个通道与多个队列通信,还是必须是1:1?
  • 队列和消费者池之间的关系是什么? 多个消费者可以订阅相同的队列吗? 多个队列可以被同一个消费者使用吗? 或者是1:1的关系?
  • 预先感谢您在这里的任何帮助!


  • Connection表示到消息代理的真实TCP连接,而Channel是其内部的虚拟连接(AMPQ连接)。 通过这种方式,您可以在应用程序内部使用尽可能多的(虚拟)连接,而不会使代理与TCP连接过载。

  • 一切都可以使用一个Channel 。 但是,如果您有多个线程,建议为每个线程使用不同的Channel

    Java客户端API指南中的通道线程安全性:

    通道实例可安全地由多个线程使用。 对通道的请求是序列化的,一次只有一个线程能够在通道上运行命令。 即便如此,应用程序应该更喜欢使用每个线程的通道,而不是在多个线程之间共享同一个通道。

    ChannelQueue之间没有直接的关系。 Channel用于向代理发送AMQP命令。 这可以是创建一个队列或类似的,但这些概念不绑定在一起。

  • 每个Consumer运行在从消费者线程池分配的自己的线程中。 如果多个消费者订阅了相同的队列,那么代理使用循环法在他们之间平均分配消息。 参见教程二:“工作队列”。

    也可以将同一个Consumer附加到多个队列中。 您可以将消费者理解为回叫。 每次消息到达队列时,都会调用这些消息。 对于Java客户端的情况,每个消费者都有一个方法handleDelivery(...) ,它表示回调方法。 你通常做的是,子类DefaultConsumer并重写handleDelivery(...) 。 注意:如果您将相同的Consumer实例附加到多个队列,则此方法将由不同的线程调用。 所以必要时请注意同步。


  • 我发现这篇文章解释了AMQP模型的所有方面,其中,频道是一个。 我发现它对我的理解非常有帮助

    https://www.rabbitmq.com/tutorials/amqp-concepts.html

    某些应用程序需要多个连接到AMQP代理。 但是,不希望同时打开许多TCP连接,因为这样做会占用系统资源并使配置防火墙变得更加困难。 AMQP 0-9-1连接与可被认为是“共享单个TCP连接的轻量级连接”的通道复用。

    对于使用多个线程/进程进行处理的应用程序,通常为每个线程/进程打开一个新通道并且不共享它们之间的通道。

    特定通道上的通信与另一个通道上的通信完全分离,因此每个AMQP方法都会携带一个客户端用来确定该方法适用于哪个通道的通道号(例如,因此需要调用哪个事件处理程序) 。


    对AMQP协议“底层”所做的概念性理解很有用。 我认为AMQP 0.9.1选择部署的文档和API使得这个特别令人困惑,所以这个问题本身就是许多人必须面对的问题。

    TL; DR

    连接是与AMQP服务器的物理协商TCP套接字。 正确实施的客户端将为每个应用程序提供其中一种线程安全的线程可共享的应用程序。

    通道是连接上的单个应用程序会话。 线程将有一个或多个这些会话。 AMQP体系结构0.9.1是这些不被线程共享的,并且当创建它的线程完成它时应该被关闭/销毁。 当发生各种协议违规时,它们也被服务器关闭。

    消费者是一种虚拟构造,表示特定频道上存在“邮箱”。 消费者的使用告诉代理将消息从特定队列推送到该信道端点。

    连接事实

    首先,正如其他人已经正确指出的那样, 连接是表示到服务器的实际TCP连接的对象。 连接在AMQP中的协议级别指定,并且与代理的所有通信都发生在一个或多个连接上。

  • 由于它是实际的TCP连接,因此它具有IP地址和端口号。
  • 协议参数是以每个客户端为基础协商的,作为建立连接的一部分(一个称为握手的过程。
  • 它的设计是长寿命的; 有少数情况下连接闭合是协议设计的一部分。
  • 从OSI角度来看,它可能位于第6层的某处
  • Heartbeats可以设置为监视连接状态,因为TCP本身不包含任何内容。
  • 最好有一个专用线程管理对底层TCP套接字的读写操作。 绝大多数,即使不是全部,RabbitMQ客户端都会这样做。 在这方面,它们通常是线程安全的。
  • 相对而言,连接是“昂贵的”创建(由于握手),但实际上,这并不重要。 大多数进程真的只需要一个连接对象。 但是,如果您发现需要比单个线程/套接字可提供更多的吞吐量(不太可能使用当前的计算技术),则可以维护池中的连接。
  • 频道的事实

    一个频道是应用程序会话,为你的每一个应用程序打开与RabbitMQ代理进行通信。 它通过单一连接进行操作,并代表与经纪人的会话。

  • 由于它代表了应用程序逻辑的逻辑部分,因此每个通道都通常存在于其自己的线程中。
  • 通常,由您的应用程序打开的所有频道将共享一个连接(它们是在连接上运行的轻量级会话)。 连接是线程安全的,所以这是好的。
  • 大多数AMQP操作都是通过频道进行的。
  • 从OSI层的角度来看,频道可能在第7层左右。
  • 通道被设计成暂时的 ; AMQP设计的一部分是通道在响应错误时通常关闭(例如,在删除现有队列之前重新声明具有不同参数的队列)。
  • 由于它们是暂时的,因此您的应用不应将频道集中在一起。
  • 服务器使用整数来标识通道。 当管理连接的线程接收到一个特定通道的数据包时,它使用这个数字告诉代理该数据包属于哪个通道/会话。
  • 通道通常不是线程安全的,因为在线程之间共享它们是没有意义的。 如果您有另一个需要使用代理的线程,则需要一个新的通道。
  • 消费者事实

    消费者是由AMQP协议定义的对象。 它既不是一个渠道,也不是一个连接,而是你的特定应用程序用作排序信息的“邮箱”。

  • “创建消费者”意味着您告诉经纪人(通过连接使用渠道)您希望通过该渠道推送给您的消息。 作为回应,经纪人将注册您在该频道上拥有一位消费者,并开始向您推送消息。
  • 通过连接推送的每条消息都将引用一个通道号码和一个消费者号码。 这样,连接管理线程(在这种情况下,在Java API中)知道如何处理消息; 那么通道处理线程也知道如何处理消息。
  • 消费者实现的差异最大,因为它实际上是特定于应用程序的。 在我的实现中,每次消息通过消费者到达时,我都选择分离任务; 因此,我有一个管理连接的线程,一个管理通道的线程(以及扩展,消费者)以及一个或多个通过消费者传递的每条消息的任务线程。
  • 关闭连接会关闭连接上的所有通道。 关闭频道可关闭频道中的所有消费者。 也可以取消消费者(不关闭频道)。 有三种情况是有道理的。
  • 通常,AMQP客户端中的消费者实现将为消费者分配一个专用通道,以避免与其他线程或代码(包括发布)的活动发生冲突。
  • 就消费者线程池的含义而言,我怀疑Java客户端正在做类似于我的客户端编程(我的客户端基于.Net客户端,但经过大量修改)的操作。

    链接地址: http://www.djcxy.com/p/34179.html

    上一篇: RabbitMQ and relationship between channel and connection

    下一篇: connect using AMQP and STOMP to same exchange