RabbitMQ和EventMachine :: defer

时间:2011-11-25 16:25:15

标签: ruby rabbitmq eventmachine

我试图让我的头围绕着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时如何执行此操作?

1 个答案:

答案 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