【问题标题】:When to use direct exchange over fanout exchange何时使用直接交换而不是扇出交换
【发布时间】:2013-02-26 23:41:17
【问题描述】:

据我所知,直接交换没有合适的用例,就像你可以用它做的任何事情一样,你可以用扇出交换做任何事情,只是更具可扩展性。

更具体地说,在阅读 RabbitMQ in Action 时,作者大量引用了类似的用例 - “假设当用户上传图片时,您需要生成缩略图。但后来营销还告诉你上传照片奖励积分。使用 RabbitMQ,你只需要创建另一个队列,并且在生产者端不做任何工作!”

但这只有如果你有远见在生产者方面创建一个扇出交换是正确的。据我了解,直接交换无法做到这一点,并且仅在您真正希望交换和队列之间紧密耦合时才适用(您不需要,因为这是消息传递系统的重点。)

这是正确的还是有实际用例?

【问题讨论】:

    标签: rabbitmq amqp


    【解决方案1】:

    与扇出交换相比,直接交换允许根据消息的路由键进行一些过滤,以确定哪些队列接收消息。使用扇出交换,没有这样的过滤,所有消息都进入所有绑定队列。

    因此,如果您与多个使用相同路由键绑定的队列进行直接交换,并且所有消息都具有此键,那么您的行为与扇出交换相同。这在tutorial 4 on the RabbitMQ website 中有更好的解释。

    在图片上传用例中,可以使用:

    • 具有两个队列的扇出交换(一个用于缩略图工作者,一个用于分数计算工作者)。路由键被忽略。

      fanout-exchange
      |--> queue --> thumbnail-worker
      `--> queue --> score-worker
      
    • 再次与两个队列直接交换。例如,队列与image-processing 键绑定,具有此键的消息将排队到两个队列。

      direct-exchange
      |--["image-processing"]--> queue --> thumbnail-worker
      `--["image-processing"]--> queue --> score-worker
      

      当然,在这种情况下,如果消息的路由键与绑定键不匹配,则任何队列都不会收到消息。

    您不能将两个工作人员放在同一个队列中,因为消息将在它们之间进行负载平衡:一个工作人员将看到一半的消息。

    【讨论】:

    • 刚刚进入rabbitMQ - 如果消费过程受到限制和理解,那么直接交换是一种更具可读性和明确性的选择,而不是必须与工人一起追踪绑定到弹出交换。
    【解决方案2】:

    您是指扇出交换还是主题交换?扇出交换与直接交换非常不同。我假设将照片发送到交易所是使用指定有照片的路由键发送的。在这种情况下,您有一个生成缩略图的消费者,当您想要添加一个新消费者时,您可以添加它并获得相同的消息,但对其执行不同的操作,即奖励积分。

    用例成立。我认为关键是交易所最初是作为直接交易所创建的。

    【讨论】:

      【解决方案3】:

      此答案与上一个答案相呼应,如果您参考此page,我相信您会描述一个特定的用例:

      直接交换通常用于在多个之间分配任务 工人(同一应用程序的实例)以循环方式进行。

      【讨论】:

      • 文档中的这句话令人困惑。事实上,如果你将多个具有相同路由键的队列绑定到一个直接交换器,如果路由键匹配,它们都会收到消息。这在tutorial 4 中有更好的解释。
      • @Jean-SébastienPédron - 我和你有同样的困惑,但是阅读下一条语句实际上消除了这种困惑 - "When doing so, it is important to understand that, in AMQP 0-9-1, messages are load balanced between consumers and not between queues." 这基本上意味着负载平衡发生在队列的消费端。