Rails Resque工作程序因PGError而失败:服务器意外关闭了连接

gc.*_*gc. 20 ruby postgresql activerecord ruby-on-rails resque

我在Ubuntu 9.10,Rails 2.3.4,ruby-ee 2010.01,PostgreSQL 8.4.2上有站点运行rails应用程序和resque worker在生产模式下运行

工人不断提出错误:PGError:服务器意外关闭了连接.

我最好的猜测是主resque进程建立与db的连接(例如authlogic在使用User.acts_as_authentic时这样做),同时加载rails app类,并且该连接在fork()ed进程中被破坏(退出?),所以下一个分叉孩子们得到了一些破碎的全局ActiveRecord :: Base.connection

我可以使用此示例代码重现非常类似的行为,模拟resque worker中的fork/processing.(AFAIK,libpq的用户建议无论如何都要在forked进程中重新创建连接,否则它不安全)

但是,奇怪的是,当我使用pgbouncer或pgpool-II而不是直接的pgsql连接时,不会出现这样的错误.

那么,问题是我应该在哪里以及如何挖掘以找出为什么它被破坏以进行普通连接并且正在使用连接池?还是合理的解决方法?

Chr*_*ini 55

做了一些研究/试验和错误.对于遇到同一问题的任何人.澄清gc提到的内容.

Resque.after_fork = Proc.new { ActiveRecord::Base.establish_connection }
Run Code Online (Sandbox Code Playgroud)

上面的代码应放在:/lib/tasks/resque.rake中

例如:

require 'resque/tasks'

task "resque:setup" => :environment do
  ENV['QUEUE'] = '*'

  Resque.after_fork do |job|
    ActiveRecord::Base.establish_connection
  end

end

desc "Alias for resque:work (To run workers on Heroku)"
task "jobs:work" => "resque:work"
Run Code Online (Sandbox Code Playgroud)

希望这对某人有所帮助,就像它对我一样.

  • 你是绅士和学者,肯定会让我头疼不已 (6认同)

Fra*_*eil 12

当我创建Nestor时,我遇到了同样的问题.解决方案是在分叉进程中重新建立连接.请参阅http://github.com/francois/nestor/blob/master/lib/nestor/mappers/rails/test/unit.rb#L162上的相关代码.

从我 Resque代码的非常有限的看法,我相信对#establish_connection的调用应该在这里完成:https://github.com/resque/resque/blob/master/lib/resque/worker.rb#L123

  • 谢谢,所以我只是添加了一个钩子:Resque.after_fork = Proc.new {ActiveRecord :: Base.establish_connection} (6认同)

Mag*_*der 10

您不能通过fork()(或新线程)传递libpq引用,除非您的应用程序非常小心地不以冲突的方式使用它.(比如,围绕每次尝试使用它的互斥锁,你必须永远不要关闭它).对于直接连接和使用pgbouncer,这都是相同的.如果它在pgbouncer中工作,那么由于某种原因错过了竞争条件的纯粹运气,并且最终会破裂.

如果您的程序使用分叉,则必须在fork 之后创建连接.