我正在使用rabbitmq
与amqp protocol
在我的应用程序中聊天。我希望成功收到发件人的邮件acknowledgement
。
创建了一个频道
channel = AMQP.channel
在rabbitmq上创建了一个队列
channel.queue(receiver_id, :auto_delete => false, durable: true)
频道播出
sender_exchange = channel.fanout(sender_id+"exchange")
频道发布
channel.publish(message)
现在我希望获得acknowledged
使用ruby on rails收到的邮件,让我知道我使用哪种方法获取acknowledgement
。
答案 0 :(得分:3)
答案实际上取决于“收到的消息确认”应该在您的申请中意味着什么。这有两种可能性:
在您的聊天功能中,此确认是否意味着选项1(从客户端向服务器发送的消息)或选项2(从客户端向一个或多个其他客户端发送的消息)?
Confirms (Publisher Acknowledgements)是RabbitMQ的一项功能,它扩展了AMQP,以向发布者确认代理已收到消息。这可能是选项1的最佳解决方案。它可能不是您想要的选项2,因为即使消息未路由到任何消费者,它也会确认。请参阅“何时确认消息?”上面链接的文档中的部分。
选项2有点像电子邮件客户端中的“已读回执”。它将要求接收方在收到并显示消息后发送收据消息。
要在rails中实现确认,假设您使用Bunny作为AMQP客户端,请遵循发布者确认示例here。它可能看起来像这样:
# wherever I create my channel
channel.confirm_select
# publish my messages
channel.wait_for_confirms
答案 1 :(得分:0)
如果您想知道消费者收到消息的时间(在知道经纪人收到消息后,它听起来并不像您;如果是, @Ryan Hoegg的回答将为您提供所需的信息,您需要做RPC pattern的高度异步变体。
RPC通常是同步的:你发送一个命令(在这种情况下通过RabbitMQ队列)并在它完成运行后立即得到响应。如果是"读取收据",该命令可能会在将来很长时间内执行。
如果你坚持使用RabbitMQ,下面就是你如何在概念上实现读取收据。它需要相当多的代码,因为RabbitMQ不会自动支持这个/没有原语#很长一段时间后,看看是否已收到某些内容"。读取收据可以通过每个聊天(对等对)的一个队列(和常量空间;没有备份读取通知消息填充RabbitMQ)来实现。
说Alice想要发送给Bob的消息的收据。
message_id
字段非常适合此目的。爱丽丝应该手动"标记"每条消息都有不断增加的ID。示例(Alice):
message_number = message_number + 1
sender_exchange.publish(message_body, :message_id => message_number)
alice_bob_read_receipts
(或与您的receiver_id
变量对应的内容;只要它是唯一的)。宣言应该是幂等/无条件的。该队列应声明为x-max-length
为1且x-overflow
为drop-head
(如果在较旧版本的RabbitMQ上,可能不支持x-overflow
,但默认行为将是你想要的。)示例(Alice):
read_receipt_queue = channel.queue(
"#{receiver_id}_#{sender_id}_read_receipts",
:arguments => {
"x-max-length".to_sym => 1,
"x-overflow".to_sym => "drop-head"
})
alice_bob_read_receipts
队列发布消息。 correlation_id
RabbitMQ元数据字段用于此类用途,因此可用于存储Bob读取的消息ID。示例(Bob):
read_receipt_queue = channel.queue(
"#{receiver_id}_#{sender_id}_read_receipts",
:arguments => {
"x-max-length".to_sym => 1,
"x-overflow".to_sym => "drop-head"
})
exchange = read_receipt_queue.default_exchange
# Assume we've got a list of messages Bob has "read" somewhere
# and each item in that list is the exact same triple as received
# by the Queue#consume method's block:
# http://rubybunny.info/articles/queues.html#handling_messages_with_a_block
viewed_messages.each do |delivery_info, properties, payload|
exchange.publish("", :correlation_id => properties.message_id)
end
Queue#pop
,但是&# 39;效率较低,可以阻止你的程序)。如果消费者获得任何数据,Alice应该设置她" Bob已经阅读了多达这个号码的消息"与弹出的消息correlation_id
中收到的值相反,然后更新UI /读取接收状态。只有在收到的值大于Alice之前知道的读取接收状态时才应执行该更新(因为消息可能丢失或重新传送)。示例:
read_receipt_queue.subscribe(...) do |delivery_info, properties, payload|
if properties.correlation_id > known_messages_bob_read
known_messages_bob_read = properties.correlation_id
end
end
有几种方法可以提高"读取收据的可靠性和/或行为。图案: