使用channel.Get()而不是channel.Consume()有缺点吗?

时间:2013-06-18 07:44:35

标签: go rabbitmq amqp

我使用streadway's amqp库连接rabbitmq服务器。 该库提供了channel.Consume()函数,该函数返回" < - chan Delivery "。 它还提供了一个channel.Get()函数,它返回" 交付"除其他外。

我实现了 pop()功能,我使用 channel.Get()。但是,documentation说:

"In almost all cases, using Channel.Consume will be preferred."

首选是否意味着推荐?使用channel.Get()而不是channel.Consume()有什么缺点吗?如果是,我如何使用channel.Consume()来实现Pop()函数?

2 个答案:

答案 0 :(得分:6)

据我所知,是的,“首选”的意思是“推荐”。

似乎channel.Get()不提供与channel.Consume()一样多的功能,并且由于它返回chan Delivery而在并发代码中更容易使用},而不是每个人Delivery分开。

提到的额外功能包括exclusivenoLocalnoWait,以及可选的Table args“,它们具有队列或服务器的特定语义。”

要使用Pop()实现channel.Consume()功能,您可以链接到amqp example consumer中的某些代码片段,创建channel using the Consume() function,创建function to handle the chan of Delivery这将实际实现您的Pop()功能,然后fire off the handle() func in a goroutine

关键是,如果没有任何接收,频道(在链接示例中)将阻止发送。在示例中,handle() func使用range处理整个频道,直到它为空。您只需从Pop()接收最后一个值并将其返回,就可以更好地为chan功能提供服务。每次运行时,它都会返回最新的Delivery

EDIT:用于从频道接收最新值并使用它进行处理的示例函数(这可能对您的用例不起作用,如果函数在另一个{{1}上发送Delivery可能更有用。到另一个要处理的函数。另外,我还没有测试下面的代码,它可能充满了错误)

chan

答案 1 :(得分:4)

这实际上取决于你想做什么。如果您只想从队列(第一个)获取一条消息,您可能应该使用basic.get,如果您计划处理来自队列的所有传入消息 - basic.consume是您想要的。

可能不是平台或库特定问题,而是协议理解问题。

<强> UPD

我对语言不熟悉,所以我会尽量向你简要介绍一下AMQP的细节并描述用例。

您可能遇到麻烦并且有时会花费basic.consume

使用basic.consume您有这样的工作流程:

  1. 发送basic.consume方法通知经纪人您想要接收消息
    • 虽然这是一种同步方法,但请等待来自经纪人的basic.consume-ok消息
  2. 开始从服务器收听basic.deliver消息
    • 这是一种异步方法,你应该自己照顾服务器上没有消息的情况,例如:限制阅读时间
  3. 使用basic.get您有这样的工作流程:

    1. 将同步方法basic.get发送给代理
      • 等待basic.get-ok方法,其中包含消息或basic.empty方法,表示服务器上没有可用消息
    2. 关于同步和异步方法的注意事项:同步应该有一些响应,无论异步是不是

      关于basic.qos方法prefetch-count属性的注意事项:no-ackbasic.consume上设置basic.get属性时会忽略该属性。

      Spec在basic.get上有一个注释:“此方法使用专为特定类型的应用程序设计的同步对话框直接访问队列中的消息,其中同步功能比性能更重要”用于连续消息消费。

      我的个人测试显示,使用basic.get(0.38659715652466)获取第1000行消息的速度比在RabbitMQ 3.0.1上逐一获取basic.consume消息(0.47398710250854),Erlang R14B04平均快超过15%。

      如果在主线程中仅消耗一条消息,则可能需要使用basic.get

      您仍然只能异步使用一条消息,例如在单独的线程中或使用某种事件机制。对于您的机器资源有时会更好的解决方案,但您必须注意队列中没有可用消息的情况。

      如果你必须逐个处理消息,很明显应该使用basic.consume,我认为