20

Ubuntu 9.10、Rails 2.3.4、ruby-ee 2010.01、PostgreSQL 8.4.2で、サイトを実行しているRailsアプリケーションとResqueワーカーを本番モードで実行しています。

ワーカーは常にエラーを発生させました:PGError:サーバーが予期せず接続を閉じました。

私の推測では、master resqueプロセスはdbへの接続を確立し(たとえば、authlogicはUser.acts_as_authenticを使用するときにそれを行います)、Railsアプリクラスをロードし、その接続はfork()されたプロセス(終了時に?)で破損するため、次にフォークされます子は一種の壊れたグローバルActiveRecord::Base.connectionを取得します

resqueworkerでフォーク/処理を模倣したこのサンプルコードで非常によく似た動作を再現できました。(AFAIK、libpqのユーザーは、とにかくフォークされたプロセスで接続を再作成することをお勧めします。そうしないと、安全ではありません)

しかし、奇妙なことに、直接pgsql接続の代わりにpgbouncerまたはpgpool-IIを使用すると、そのようなエラーは表示されません。

それで、問題は、プレーン接続で壊れて接続プールで動作している理由を見つけるために、どこでどのように掘り下げる必要があるかということです。または合理的な回避策?

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

アプリケーションが競合する方法で使用しないように細心の注意を払っていない限り、libpq参照をfork()を介して(または新しいスレッドに)渡すことはできません。(同様に、それを使用しようとするすべての試みの周りのミューテックスであり、決して閉じてはなりません)。これは、直接接続とpgbouncerの使用の両方で同じです。それがpgbouncerで機能した場合、それは何らかの理由で競合状態を逃した純粋な運であり、最終的には壊れます。

プログラムでフォークを使用する場合は、フォークのに接続を作成する必要があります。

于 2010-04-10T09:25:24.263 に答える
0

Apache構成を変更し、追加します

PassengerSpawnMethod conservative
于 2012-09-23T21:10:32.377 に答える