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

我在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连接时,不会出现这样的错误。

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

当我创建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

经过一番研究/试验和错误。 对于遇到同一问题的任何人。 澄清gc提到的内容。

Resque.after_fork = Proc.new { ActiveRecord::Base.establish_connection } 

上面的代码应放在:/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" 

希望这能帮助某人,就像它对我一样。

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

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

更改Apache配置并添加

 PassengerSpawnMethod conservative 

我的所有Mailer类都遇到了这个问题,我需要调用ActiveRecord::Base.verify_active_connections! 在邮件程序方法中,以确保建立连接。