2010-04-10 10 views
20

Ho sito in esecuzione l'applicazione rotaie e lavoratori Resque in esecuzione in modalità di produzione, su Ubuntu 9.10, Rails 2.3.4, ruby-ee 2010.01, PostgreSQL 8.4.2lavoratori Rails Resque falliscono con PGError: server ha chiuso la connessione inaspettatamente

I worker hanno costantemente generato errori: PGError: il server ha chiuso la connessione in modo imprevisto.

La mia ipotesi migliore è che il processo di resque master stabilisca la connessione a db (ad es. Authlogic lo fa quando si usa User.acts_as_authentic), mentre carica le classi di app delle rotaie e quella connessione diventa danneggiata nel processo di fork() ed (all'uscita?) , quindi i bambini biforcuti diventano di tipo ActiveRecord globale rotto :: Base.connection

Potrei riprodurre un comportamento molto simile con questo sample code che imita fork/processing in resque worker. (AFAIK, gli utenti di libpq consigliano di ricreare le connessioni in processo biforcato comunque, altrimenti non è sicuro)

Ma, la cosa strana è che quando uso pgbouncer o pgpool-II invece di collegamento diretto pgsql, tali errori non compaiono .

Quindi, la domanda è dove e come dovrei scavare per scoprire perché è rotto per connessione semplice e funziona con i pool di connessione? O soluzione ragionevole?

risposta

12

Quando ho creato Nestor, ho avuto lo stesso tipo di problema. La soluzione era ristabilire la connessione nel processo biforcato. Vedere il codice relativo al http://github.com/francois/nestor/blob/master/lib/nestor/mappers/rails/test/unit.rb#L162

Dal mio molto sguardo limitato al codice Resque, credo che una chiamata a #establish_connection dovrebbe essere fatto proprio qui: https://github.com/resque/resque/blob/master/lib/resque/worker.rb#L123

+6

Grazie, quindi ho semplicemente aggiunto hook: Resque.after_fork = Proc.new {ActiveRecord :: Base.establish_connection} –

+1

Potrei trovarmi di fronte a un problema simile. Puoi dirmi come e dove hai aggiunto il "gancio"? –

+0

link in basso è rotto – botbot

9

Non è possibile passare un riferimento libpq attraverso una forchetta () (o in una nuova discussione), a meno che l'applicazione non si occupi molto attentamente di non utilizzarla in modi contrastanti. (Come, un mutex attorno a ogni singolo tentativo di usarlo, e non devi mai chiuderlo). Questo è lo stesso per entrambe le connessioni dirette e usando pgbouncer. Se ha funzionato in pgbouncer, è stata pura fortuna nel perdere una condizione di gara per qualche motivo, e alla fine si rompe.

Se il programma utilizza biforcano, è necessario creare la connessione dopo forcella.

55

Dopo aver fatto un po 'di ricerche/tentativi ed errori. Per tutti coloro che incontrano lo stesso problema. Per chiarire cosa citato gc.

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

Sopra codice deve essere inserito in: /lib/tasks/resque.rake

Ad esempio:

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" 

Spero che questo aiuti qualcuno, per quanto ha fatto per me.

+6

sei un gentiluomo e uno studioso, mi ha salvato alcuni mal di testa di sicuro – Jimmy

+1

Questo è perfetto! ... ma potresti voler rimuovere la riga 'ENV ['CODE']', dato che questo rovinerà la generazione di tutti gli operatori specifici della coda impostandoli a '*' – nessur

+0

mio: compito di installazione doveva essere all'interno : resque task. (Non un resque: setup inside: resque!) A causa di ciò all'inizio non ha funzionato per me. Volevo solo dire alle persone di controllare l'ereditarietà del compito. – scaryguy

0

configurazione di Apache Modifica e aggiungere

PassengerSpawnMethod conservative 
0

ho avuto questo problema con tutti i miei corsi Mailer e avevo bisogno di chiamare ActiveRecord::Base.verify_active_connections! entro i metodi mailer al fine di garantire un collegamento è stato fatto.

Problemi correlati