我试图让我的头围绕着RabbitMQ。我想要一个队列来监听,当它收到一条消息时,我希望它回复一个匿名队列,该队列通过带有多条消息的reply_to
标题指定。
到目前为止,我有以下任务,即reply_to
消息的使用者和订阅者:
desc "start_consumer", "start the test consumer"
def start_consumer
puts "Running #{AMQP::VERSION} version of the gem"
AMQP.start(:host => "localhost", :user => "guest", :password => "guest", :vhost => "/",
:logging => true, :port => 5672) do |connection|
channel = AMQP::Channel.new(connection)
requests_queue = channel.queue("one", :exclusive => true, :auto_delete => true)
Signal.trap("INT") do
connection.close do
EM.stop{exit}
end
end
channel.prefetch(1)
requests_queue.subscribe(:ack => true) do |header, body|
puts "received in server #{body.inspect}"
(0..5).each do |n|
header.ack
reply = {:reply => "Respone #{n}", :is_last => (n == 5)}
AMQP::Exchange.default.publish(
MultiJson.encode(reply),
:routing_key => header.reply_to,
:correlation_id => header.correlation_id
)
sleep(2)
end
end
puts " [x] Awaiting RPC requests"
end
end
我的主叫代码是:
def publish(urlSearch, routing_key)
EM.run do
corr_id = rand(10_000_000).to_s
requests ||= Hash.new
connection = AMQP.connect(:host => "localhost")
callback_queue = AMQP::Channel.new(connection).queue("", :exclusive => true)
callback_queue.subscribe do |header, body|
reply = MultiJson.decode(body)
if reply[:is_last.to_s]
connection.close do
EM.stop{exit}
end
end
end
callback_queue.append_callback(:declare) do
AMQP::Exchange.default.publish(MultiJson.encode(urlSearch), :routing_key => routing_key, :reply_to => callback_queue.name, :correlation_id => corr_id)
end
end
问题是在迭代中的所有消息都已发布之前不会发送消息。
那是在(0..5)
循环中的迭代完成之后,所有消息都被发布。
有人告诉我,使用EventMachine::defer
可能是一个选项,但我不知道如何将其应用于循环。
有人能建议如何解决这个问题的指针吗? EventMachine::defer
是一个不错的选择,如果是,那么在使用AMQP.start
时如何执行此操作?
答案 0 :(得分:0)
使用EM时要记住的事情是反应器本身是单螺纹的。因此,它等待循环在任何发送之前完成的原因是因为循环占用了那个单线程。 (你真的,真的,真的不想在EM应用程序中使用睡眠。你正在阻止整个反应堆,什么都不会发生。)
如果您希望发布消息,或者其他任何其他EM动作发生(定时器触发,接收其他数据等),您必须让反应器循环。
您可以使用类似EM :: Iterator的方式为您安排工作,例如:
EM::Iterator.new(0..5).each do |n, iter|
reply = {:reply => "Response #{n}", :is_last => (n == 5)}
AMQP::Exchange.default.publish(MultiJson.encode(reply),
:routing_key => header.reply_to,
:correlation_id => header.correlation_id)
iter.next
end
header.ack