20

我在 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 应用程序类,并且该连接在 fork()ed 进程中损坏(退出时?),所以下一个分叉孩子们得到一种破碎的全球 ActiveRecord::Base.connection

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

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

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

4

5 回答 5

55

在做了一些研究/反复试验之后。对于遇到相同问题的任何人。澄清 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"

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

于 2011-04-01T22:07:18.410 回答
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

于 2010-04-10T04:06:05.643 回答
10

您不能通过 fork()(或新线程)传递 libpq 引用,除非您的应用程序非常注意不以冲突的方式使用它。(例如,每次尝试使用它时都有一个互斥锁,并且您永远不能关闭它)。这对于直接连接和使用 pgbouncer 都是一样的。如果它在 pgbouncer 中工作,那纯粹是因为某种原因错过了比赛条件,并且最终会中断。

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

于 2010-04-10T09:25:24.263 回答
0

更改 Apache 配置并添加

PassengerSpawnMethod conservative
于 2012-09-23T21:10:32.377 回答
0

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

于 2013-04-28T07:15:56.163 回答