2010-04-10 13 views
20

tengo sitio ejecuta la aplicación de los carriles y los trabajadores resque ejecuta en el modo de producción, en Ubuntu 9.10, rieles 2.3.4, rubí-EE 2010.01, PostgreSQL 8.4.2trabajadores rieles Resque fallan con PGError: servidor ha cerrado la conexión de forma inesperada

Trabajadores constantemente levantaron errores: PGError: el servidor cerró la conexión inesperadamente.

Supongo que el proceso maestro resque establece conexión con db (p. Ej. Authlogic cuando usa User.acts_as_authentic), al cargar clases de aplicación de rieles, y esa conexión se daña en fork() proceso de ed (¿al salir?) , así que los próximos hijos con bifurcaciones se rompen globalmente ActiveRecord :: Base.connection

Pude reproducir un comportamiento muy similar con esta sample code imitación de fork/processing en resque worker. (AFAIK, los usuarios de libpq recomiendan volver a crear conexiones en el proceso bifurcado de todos modos, de lo contrario no es seguro)

Pero, lo curioso es que cuando uso pgbouncer o pgpool-II en lugar de conexión pgsql directa, tales errores no aparecen .

Entonces, la pregunta es ¿dónde y cómo debo excavar para descubrir por qué está roto para la conexión normal y está trabajando con pools de conexión? O una solución razonable?

Respuesta

12

Cuando creé Nestor, tuve el mismo tipo de problema. La solución fue restablecer la conexión en el proceso bifurcado. Ver el código correspondiente al http://github.com/francois/nestor/blob/master/lib/nestor/mappers/rails/test/unit.rb#L162

Desde mi mirada limitada al código Resque, creo que una llamada a #establish_connection debe hacerse justo por aquí: https://github.com/resque/resque/blob/master/lib/resque/worker.rb#L123

+6

Gracias, así que simplemente agregué el gancho: Resque.after_fork = Proc.new {ActiveRecord :: Base.establecer_conexión} –

+1

Puede que tenga un problema similar. ¿Me puede decir cómo y dónde agregó el "gancho"? –

+0

enlace inferior está roto – botbot

9

no se puede pasar una referencia libpq a través de un tenedor () (o a un nuevo hilo), a menos que su aplicación tenga mucho cuidado de no usarlo de manera conflictiva. (Como, un mutex alrededor de cada intento de usarlo, y nunca debes cerrarlo). Esto es lo mismo para las conexiones directas y el uso de pgbouncer. Si funcionó en pgbouncer, eso fue pura suerte al perder una condición de carrera por alguna razón, y eventualmente se romperá.

Si el programa utiliza bifurcan, se debe crear la conexión después de el tenedor.

55

Después de hacer un poco de investigación/ensayo y error. Para cualquiera que se encuentre con el mismo problema. Para aclarar qué gc mencionado.

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

Por encima de código debe insertarse en: /lib/tasks/resque.rake

Por ejemplo:

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" 

Espero que esto ayude a alguien, tanto como lo hizo por mí.

+6

eres un caballero y un erudito, me salvó algunos dolores de cabeza con seguridad – Jimmy

+1

¡Esto es perfecto! ... pero es posible que desee eliminar la línea 'ENV ['QUEUE']', ya que eso arruinaría el desove de los trabajadores específicos de la cola al establecerlos en '*' – nessur

+0

mi: se suponía que la tarea de instalación estaba dentro : tarea resque (No es un resque: configuración dentro: resque!) Por eso al principio esto no funcionó para mí. Solo quería decirle a las personas que revisen la tarea inherentemente. – scaryguy

0

Cambiar la configuración de Apache y añadir

PassengerSpawnMethod conservative 
0

yo tuvimos este problema con todas mis clases Mailer y yo necesitaba para llamar ActiveRecord::Base.verify_active_connections! dentro de los métodos anuncio publicitario con el fin de garantizar una conexión fue hecha.

Cuestiones relacionadas