代码之家  ›  专栏  ›  技术社区  ›  user1768830

RabbitMQ以及通道和连接之间的关系

  •  227
  • user1768830  · 技术社区  · 12 年前

    这个 RabbitMQ Java client 具有以下概念:

    • Connection -到RabbitMQ服务器实例的连接
    • Channel - ???
    • 使用者线程池-使用RabbitMQ服务器队列中的消息的线程池
    • 队列-一种按FIFO顺序保存消息的结构

    我正在努力理解这种关系, 更重要的是 这个 协会 他们之间。

    1. 我仍然不太确定 频道 是的,除了这是您发布和使用的结构,并且它是从打开的连接创建的之外。如果有人能向我解释“频道”代表什么,这可能有助于澄清一些问题。
    2. 通道和队列之间的关系是什么?同一个通道可以用于与多个队列通信吗?还是必须是1:1?
    3. 队列和消费者池之间的关系是什么?多个消费者可以订阅同一队列吗?同一消费者是否可以使用多个队列?还是关系是1:1?
    4 回复  |  直到 5 年前
        1
  •  250
  •   Lovvan    6 年前
    1. A. Connection 表示到消息代理的真实TCP连接,而 Channel 是其中的一个虚拟连接(AMQP连接)。这样,您就可以在应用程序中使用任意数量的(虚拟)连接,而不会使代理过载TCP连接。

    2. 你可以用一个 频道 为了一切。但是,如果您有多个线程,建议使用不同的 频道 对于每个线程。

      Channel thread-safety in Java Client API Guide :

      通道实例对于多个线程使用是安全的。请求进入 通道被序列化,只有一个线程能够运行 命令。即便如此,应用程序应该更喜欢 每个线程使用一个通道,而不是在 多线程。

      两者之间没有直接关系 频道 Queue A. 频道 用于向代理发送AMQP命令。这可以是创建队列或类似的操作,但这些概念并没有绑定在一起。

    3. 每个 Consumer 在从使用者线程池分配的自己的线程中运行。如果多个消费者订阅了同一个队列,则代理使用循环来在它们之间平均分配消息。看见 Tutorial two: "Work Queues" .

      也可以连接 消费者 到多个队列。 你可以把消费者理解为回调。每当消息到达Consumer绑定到的队列时,都会调用这些函数。对于Java客户端,每个Consumer都有一个方法 handleDelivery(...) ,表示回调方法。你通常要做的是 DefaultConsumer 和超控 处理交付(…) 。注意:如果将同一Consumer实例附加到多个队列,则此方法将由不同的线程调用。因此,如有必要,请注意同步。

        2
  •  81
  •   theMayer    8 年前

    在这里,对AMQP协议“在引擎盖下”的作用有一个很好的概念理解是有用的。我想说的是,AMQP 0.9.1选择部署的文档和API使这一点特别令人困惑,因此这个问题本身是许多人必须解决的问题。

    TL;博士

    A. 联系 是与AMQP服务器进行物理协商的TCP套接字。正确实现的客户端每个应用程序都有一个这样的线程,线程安全,可以在线程之间共享。

    A. 频道 是连接上的单个应用程序会话。线程将具有一个或多个这样的会话。AMQP体系结构0.9.1是指这些不在线程之间共享,并且应该在创建它的线程完成时关闭/销毁。当发生各种协议冲突时,服务器也会关闭它们。

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

    连接事实

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

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

    渠道事实

    A. 频道 是为应用程序的每一部分打开的应用程序会话,用于与RabbitMQ代理通信。它在单个 联系 ,表示 一场 与经纪人。

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

    消费者事实

    消费者是由AMQP协议定义的对象。它既不是一个通道,也不是一个连接,而是您的特定应用程序用作某种“邮箱”来投递邮件的东西。

    • “创建消费者”意味着你告诉经纪人(使用 频道 通过 联系 )您希望通过该频道向您推送消息。作为回应,经纪人将注册您有 消费者 在频道上,并开始向您推送消息。
    • 通过连接推送的每条消息都将引用 通道编号 和一个 消费者号码 通过这种方式,连接管理线程(在这种情况下,在Java API内)知道如何处理消息;然后,通道处理线程也知道如何处理消息。
    • 消费者实现具有最广泛的变化,因为它实际上是特定于应用程序的。在我的实现中,每次消息通过消费者到达时,我都选择剥离一个任务;因此,我有一个管理连接的线程,一个管理通道(以及扩展的消费者)的线程,以及通过消费者传递的每个消息的一个或多个任务线程。
    • 正在关闭 联系 关闭连接上的所有通道。正在关闭 频道 关闭频道上的所有消费者。也可以 取消 消费者(不关闭频道)。在各种情况下,做这三件事中的任何一件都是有意义的。
    • 通常,消费者在AMQP客户端中的实现将为消费者分配一个专用通道,以避免与其他线程或代码的活动(包括发布)发生冲突。

    就你所说的消费者线程池而言,我怀疑Java客户端正在做一些类似于我为客户端编程的事情(我的客户端是基于.Net客户端的,但经过了大量修改)。

        3
  •  25
  •   Community Mohan Dere    5 年前

    我找到了这篇文章,它解释了AMQP模型的各个方面,通道就是其中之一。我发现这对我的理解很有帮助

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

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

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

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

        4
  •  10
  •   Atul Jain    6 年前

    同类之间存在关系 一个TCP连接可以有多个通道 .

    频道 :它是连接中的一个虚拟连接。当发布或使用队列中的消息时,这一切都是通过通道完成的 联系 :它是应用程序和RabbitMQ代理之间的TCP连接。

    在多线程体系结构中,每个线程可能需要一个单独的连接。这可能会导致TCP连接的利用不足,也会给操作系统增加开销,以在网络高峰时间建立所需的TCP连接。该系统的性能可能会大幅降低。这就是通道的用武之地,它在TCP连接中创建虚拟连接。它直接减少了操作系统的开销,还允许我们以更快速、可靠和同时的方式执行异步操作。 enter image description here