Pergunta

Eu tenho o local de execução do Site Rails e os trabalhadores resques executados no modo de produção, no Ubuntu 9.10, Rails 2.3.4, Ruby-ee 2010.01, PostgreSQL 8.4.2

Trabalhadores constantemente levantaram erros: Pgerror: o servidor fechou a conexão inesperadamente.

Meu melhor palpite é que o processo mestre resque estabelece a conexão com o banco de dados (por exemplo, authlogic faz isso quando usa user.acts_as_authentic), enquanto carrega as classes de aplicativos Rails, e essa conexão se corrompe no processo de bifurcação () (na saída?), Então, o próximo bifurcado forçado As crianças ficam meio quebradas do ActiveRecord Global :: base.Connection

Eu poderia reproduzir um comportamento muito semelhante com isso Código de amostra imitando o garfo/processamento no trabalhador resque. (Afaik, usuários da libpq recomendaram recriar conexões em processo bifurcado de qualquer maneira, caso contrário, não é seguro)

Mas, o mais estranho é que, quando uso o PGBouncer ou o PGPOOL-II em vez da conexão direta PGSQL, esses erros não aparecem.

Então, a questão é onde e como devo cavar para descobrir por que está quebrada para conexão simples e está trabalhando com pools de conexão? Ou solução alternativa razoável?

Foi útil?

Solução

Quando eu criei Nestor, Eu tive o mesmo tipo de problema. A solução foi restabelecer a conexão no processo bifurcado. Veja o código relevante em http://github.com/francois/nestor/blob/master/lib/nestor/mappers/rails/test/unit.rb#l162

Do meu muito Olhe limitada no código Resque, acredito que uma chamada para #establish_connection deve ser feita corretamente aqui: https://github.com/resque/resque/blob/master/lib/resque/worker.rb#l123

Outras dicas

Depois de fazer um pouco de pesquisa / tentativa e erro. Para quem está se deparar com o mesmo problema. Para esclarecer o que o GC mencionou.

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

O código acima deve ser colocado em: /lib/tasks/resque.rake

Por exemplo:

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 isso ajude alguém, tanto quanto para mim.

Você não pode passar uma referência LibPQ em um garfo () (ou para um novo thread), a menos que seu aplicativo cuide muito de não usá -lo de maneiras conflitantes. (Como um mutex em torno de cada tentativa de usá -lo, e você nunca deve fechá -lo). Isso é o mesmo para as conexões diretas e o uso do PGBouncer. Se funcionasse em Pgbouncer, isso foi pura sorte ao perder uma condição de corrida por algum motivo e acabará por quebrar.

Se o seu programa usa forking, você devo Crie a conexão depois o garfo.

Altere a configuração do Apache e adicione

PassengerSpawnMethod conservative

Eu tive esse problema com todas as minhas aulas de Mailer e precisava ligar ActiveRecord::Base.verify_active_connections! Dentro dos métodos Mailer, a fim de garantir que uma conexão fosse feita.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top