带有PhusionPassenger / Rails的AMQP / RabbitMQ-Server / EventMachine只能收到第一条消息

时间:2013-07-30 19:30:20

标签: ruby-on-rails rabbitmq passenger amqp eventmachine

我在我的Ruby on Rails应用程序中使用AMQP / RabbitMQ。

我将以下amqp.rb文件放在config / initializers下:(从食谱中复制并更改:http://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html#sthash.iqCWUtOn.dpbs

require 'amqp'

# References:
#   1. Getting Started with AMQP and Ruby
#      http://rubyamqp.info/articles/getting_started/
#   2. EventMachine and Rails
#      http://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html#sthash.iqCWUtOn.dpbs
#   3. Connecting to the broker, integrating with Ruby on Rails, Merb and Sinatra
#      http://rubyamqp.info/articles/connecting_to_broker/
module AppEventMachine
  def self.start
    if defined?(PhusionPassenger)
      Rails.logger.info "###############################################################################"
      Rails.logger.info "Running EventMachine/Rails with PhusionPassenger ......"
      Rails.logger.info "###############################################################################"
      PhusionPassenger.on_event(:starting_worker_process) do |forked|
      # =>  for passenger, we need to avoid orphaned threads
        if forked && EventMachine.reactor_running?
          EventMachine.stop
        end

        spawn_eventmachine_thread
        die_gracefully_on_signal
      end
    else
      Rails.logger.info "###############################################################################"
      Rails.logger.info "PhusionPassenger is not running.  Probably you are running Rails locally ......"
      Rails.logger.info "###############################################################################"

      # faciliates debugging
      Thread.abort_on_exception = true
      # just spawn a thread and start it up
      spawn_eventmachine_thread unless defined?(Thin)
      # Thin is built on EventMachine, doesn't need this thread
    end
  end

  def self.spawn_eventmachine_thread
    Thread.new {
      EventMachine.run do
        AMQP.channel ||= AMQP::Channel.new(AMQP.connect(:host => '127.0.0.1')) # Q_SERVER, :user=> Q_USER, :pass => Q_PASS, :vhost => Q_VHOST ))
        AMQP.channel.on_error(&method(:handle_channel_exception))
        AMQP.channel.queue(MixpanelJob::QUEUE_NAME, :exclusive => true)
                    .subscribe { |metadata, payload| MixpanelJob::handle_sending(metadata, payload) }
      end
    }
  end

  def self.handle_channel_exception(channel, channel_close)
    Rails.logger.error "###############################################################################"
    Rails.logger.error "Oops... a channel-level exception: code = #{channel_close.reply_code}, message = #{channel_close.reply_text}"
    Rails.logger.error "###############################################################################"
  end

  def self.die_gracefully_on_signal
    Signal.trap("INT") {
      Rails.logger.error "###############################################################################"
      Rails.logger.error "Stopping the EventMachine ......"
      EventMachine.stop
      Rails.logger.error "###############################################################################"
    }
    Signal.trap("TERM") {
      Rails.logger.error "###############################################################################"
      Rails.logger.error "Stopping the EventMachine ......"
      EventMachine.stop
      Rails.logger.error "###############################################################################"
    }
  end
end

AppEventMachine.start

在我使用PhusionPassenger启动Rails后,我看到它正在运行PhusionPassenger,然后我尝试将消息发送到队列,但令我惊讶的是:

.subscribe { |metadata, payload| MixpanelJob::handle_sending(metadata, payload) }

subscribe处理程序只执行一次,即只收到第一条消息,任何其他消息(第2,第3),subscribe处理程序永远不会被调用。

1 个答案:

答案 0 :(得分:0)

感谢约书亚的评论。事实证明MixpanelJob::handl_sending失败了,它阻止了EventMachine线程。