Os trabalhadores do Rails Resque falham com o PGERROR: o servidor fechou a conexão inesperadamente
-
25-09-2019 - |
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?
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.