我使用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()函数?
答案 0 :(得分:6)
据我所知,是的,“首选”的意思是“推荐”。
似乎channel.Get()
不提供与channel.Consume()
一样多的功能,并且由于它返回chan
Delivery
而在并发代码中更容易使用},而不是每个人Delivery
分开。
提到的额外功能包括exclusive
,noLocal
和noWait
,以及可选的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
您有这样的工作流程:
basic.consume
方法通知经纪人您想要接收消息
basic.consume-ok
消息basic.deliver
消息
使用basic.get
您有这样的工作流程:
basic.get
发送给代理
basic.get-ok
方法,其中包含消息或basic.empty
方法,表示服务器上没有可用消息关于同步和异步方法的注意事项:同步应该有一些响应,无论异步是不是
关于basic.qos
方法prefetch-count
属性的注意事项:在no-ack
或basic.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
,我认为