Hi all, I''m having issues with Unicorn and connecting to RabbitMQ using the tmm1-amqp gem. I''ve tried lots of approaches. The classic initializer with Thread.new { EM.run } for the Rails app and even tried using the Qusion library. (https://github.com/danielsdeleo/qusion) I''ve made a simple mod to Qusion for it to monkey patch unicorn too. The code looks like: /vendor/plugins/qusion/lib/amqp.rb module AMQP def self.start_web_dispatcher(amqp_settings={}) @settings = settings.merge(amqp_settings) case Qusion::ServerSpy.server_type when :passenger PhusionPassenger.on_event(:starting_worker_process) do |forked| if forked EM.kill_reactor Thread.current[:mq], @conn = nil, nil end Thread.new { start } die_gracefully_on_signal end when :standard Thread.new { start } die_gracefully_on_signal when :evented die_gracefully_on_signal when :none # << HERE Thread.new { start } die_gracefully_on_signal else raise ArgumentError, "AMQP#start_web_dispatcher requires an argument of [:standard|:evented|:passenger|:none]" end end def self.die_gracefully_on_signal Signal.trap("INT") { AMQP.stop { EM.stop } } Signal.trap("TERM") { AMQP.stop { EM.stop } } end end See the :none case? It used to be empty and return nil. Now it has the same behavior as the non- evented :standard server. The problem is that the "server_spy" wasn''t recognizing Unicorn. So far so good. Originally, the AMQP/Qusion conf goes into config/environment.rb config.after_initialize do Qusion.start(:user => ''guest'',:pass => ''mypass'') end However, when I publish messages to the queue, it just isn''t posted. It silently fails. I''ve then tried to put this on config/unicorn.rb: before_fork do |server,worker| Qusion.start(:user => ''guest'',:pass => ''mypass'') MQ.new.queue(''jobs'').publish(''hey!'') end And the hey! message is posted. However, it only works from here, the MQ.new.queue on the app code fails silently. Any ideas on what might be happenig?
Marcelo de Moraes Serpa <fullofcaffeine at gmail.com> wrote:> Hi all, > > I''m having issues with Unicorn and connecting to > RabbitMQ using the tmm1-amqp gem. > > I''ve tried lots of approaches. > > The classic initializer with Thread.new { EM.run } > for the Rails app and even tried using > the Qusion library. > > (https://github.com/danielsdeleo/qusion) > > I''ve made a simple mod to Qusion for it to monkey patch > unicorn too. > > The code looks like: > > /vendor/plugins/qusion/lib/amqp.rb > > module AMQP > def self.start_web_dispatcher(amqp_settings={}) > @settings = settings.merge(amqp_settings) > case Qusion::ServerSpy.server_type > when :passenger > PhusionPassenger.on_event(:starting_worker_process) do |forked|<side note>maybe adding a similar hook to Unicorn for library/app authors to use would be a good idea.</side note>> if forked > EM.kill_reactor > Thread.current[:mq], @conn = nil, nil > end > Thread.new { start } > die_gracefully_on_signal > end > when :standard > Thread.new { start } > die_gracefully_on_signal > when :evented > die_gracefully_on_signal > when :none # << HERE > Thread.new { start } > die_gracefully_on_signal > else > raise ArgumentError, "AMQP#start_web_dispatcher > requires an argument of > [:standard|:evented|:passenger|:none]" > end > end > > def self.die_gracefully_on_signal > Signal.trap("INT") { AMQP.stop { EM.stop } } > Signal.trap("TERM") { AMQP.stop { EM.stop } } > endRegistering a standard at_exit {} block in the Unicorn after_fork hook would be a good idea than trapping INT and TERM, which Unicorn uses.> end > > See the :none case? It used to be empty and return nil. > > Now it has the same behavior as the non- > evented :standard server. > > The problem is that the "server_spy" wasn''t > recognizing Unicorn. So far so > good. > > Originally, the AMQP/Qusion conf goes into config/environment.rb > > config.after_initialize do > > Qusion.start(:user => ''guest'',:pass => ''mypass'') > end > > > However, when I publish messages to the queue, > it just isn''t posted. It silently fails. > > I''ve then tried to put this on config/unicorn.rb: > > before_fork do |server,worker| > Qusion.start(:user => ''guest'',:pass => ''mypass'') > MQ.new.queue(''jobs'').publish(''hey!'') > end > > And the hey! message is posted. > > However, it only works from here, the MQ.new.queue on the app code > fails silently. > > Any ideas on what might be happenig?Is preload_app true? Then you''re probably trying to share sockets across processes and confusing EM or AMQP. Instead of using before_fork above, you should probably be using after_fork: before_fork do |server,worker| Qusion.start(:user => ''guest'',:pass => ''mypass'') MQ.new.queue(''jobs'').publish(''hey!'') end I''m not very familiar with AMQP, but the Unicorn process is strictly an AMQP sender/client and doesn''t listen as a server on a port, right? If so, the above before_fork config *should* work for you. Let us know how it goes! -- Eric Wong
We use unicorn + sinatra + tmm1/amqp, and I can say for a fact that you must initialize the AMQP connection in after_fork. Eric is probably right about the fd sharing from before_fork. In the rails-specific context, if preload_app is true, it''s possible that using config.after_initialize {} will still result in the AMQP initialization occurring before the fork. cheers, --jordan On Nov 9, 2010, at 4:55 PM, Eric Wong wrote:> Marcelo de Moraes Serpa <fullofcaffeine at gmail.com> wrote: >> Hi all, >> >> I''m having issues with Unicorn and connecting to >> RabbitMQ using the tmm1-amqp gem. >> >> I''ve tried lots of approaches. >> >> The classic initializer with Thread.new { EM.run } >> for the Rails app and even tried using >> the Qusion library. >> >> (https://github.com/danielsdeleo/qusion) >> >> I''ve made a simple mod to Qusion for it to monkey patch >> unicorn too. >> >> The code looks like: >> >> /vendor/plugins/qusion/lib/amqp.rb >> >> module AMQP >> def self.start_web_dispatcher(amqp_settings={}) >> @settings = settings.merge(amqp_settings) >> case Qusion::ServerSpy.server_type >> when :passenger >> PhusionPassenger.on_event(:starting_worker_process) do |forked| > > <side note>maybe adding a similar hook to Unicorn for library/app authors > to use would be a good idea.</side note> > >> if forked >> EM.kill_reactor >> Thread.current[:mq], @conn = nil, nil >> end >> Thread.new { start } >> die_gracefully_on_signal >> end >> when :standard >> Thread.new { start } >> die_gracefully_on_signal >> when :evented >> die_gracefully_on_signal >> when :none # << HERE >> Thread.new { start } >> die_gracefully_on_signal >> else >> raise ArgumentError, "AMQP#start_web_dispatcher >> requires an argument of >> [:standard|:evented|:passenger|:none]" >> end >> end >> >> def self.die_gracefully_on_signal >> Signal.trap("INT") { AMQP.stop { EM.stop } } >> Signal.trap("TERM") { AMQP.stop { EM.stop } } >> end > > Registering a standard at_exit {} block in the Unicorn > after_fork hook would be a good idea than trapping INT > and TERM, which Unicorn uses. > >> end >> >> See the :none case? It used to be empty and return nil. >> >> Now it has the same behavior as the non- >> evented :standard server. >> >> The problem is that the "server_spy" wasn''t >> recognizing Unicorn. So far so >> good. >> >> Originally, the AMQP/Qusion conf goes into config/environment.rb >> >> config.after_initialize do >> >> Qusion.start(:user => ''guest'',:pass => ''mypass'') >> end >> >> >> However, when I publish messages to the queue, >> it just isn''t posted. It silently fails. >> >> I''ve then tried to put this on config/unicorn.rb: >> >> before_fork do |server,worker| >> Qusion.start(:user => ''guest'',:pass => ''mypass'') >> MQ.new.queue(''jobs'').publish(''hey!'') >> end >> >> And the hey! message is posted. >> >> However, it only works from here, the MQ.new.queue on the app code >> fails silently. >> >> Any ideas on what might be happenig? > > Is preload_app true? Then you''re probably trying to share sockets > across processes and confusing EM or AMQP. > > Instead of using before_fork above, you should probably > be using after_fork: > > before_fork do |server,worker| > Qusion.start(:user => ''guest'',:pass => ''mypass'') > MQ.new.queue(''jobs'').publish(''hey!'') > end > > I''m not very familiar with AMQP, but the Unicorn process is strictly an > AMQP sender/client and doesn''t listen as a server on a port, right? > If so, the above before_fork config *should* work for you. > > Let us know how it goes!
Possibly Parallel Threads
- Install amqp gem on windows 7
- Re: libguestfs error
- [PATCH] Let ovirt-test use DNS SRV to get qpidd server.
- [PATCH server] Removed workaround for qmf bug that yielded 0 cpus and 0 nics for nodes from time to time.
- preload_app = true causing - ActiveModel::MissingAttributeError: missing attribute: some_attr