setup postgres guide devcenter database_url create articles heroku connection-pooling rails-activerecord rails-postgresql heroku-postgres

postgres - Heroku+Sidekiq: ActiveRecord:: StatementInvalid: PG:: UnableToSend: SSL SYSCALL error: Se detectó EOF



heroku reset database (1)

Hola, estamos corriendo en la pila de cedros de Heroku con Unicorn y Sidekiq. Recibimos intermitentemente los siguientes errores.

BurnThis ActiveRecord::StatementInvalid: PG::UnableToSend: SSL SYSCALL error: EOF detected ActiveRecord::StatementInvalid: PG::ConnectionBad: PQconsumeInput() SSL SYSCALL error: Connection timed out

¿Alguien tiene alguna idea de cuál es la causa directa de estos errores? ¿Son demasiadas conexiones a nuestra base de datos? Ya tenemos nuestra horquilla configurada de la siguiente manera:

unicorn.rb

worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3) timeout 30 preload_app true before_fork do |server, worker| Signal.trap ''TERM'' do puts ''Unicorn master intercepting TERM and sending myself QUIT instead'' Process.kill ''QUIT'', Process.pid end defined?(ActiveRecord::Base) and ActiveRecord:: Base.connection.disconnect! end after_fork do |server, worker| Signal.trap ''TERM'' do puts ''Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'' end # other setup if defined?(ActiveRecord::Base) config = Rails.application.config.database_configuration[Rails.env] config[''adapter''] = ''postgis'' config[''pool''] = ENV[''DB_POOL''] || 5 config[''reaping_frequency''] = ENV[''DB_REAP_FREQ''] || 10 # seconds ActiveRecord::Base.establish_connection(config) end end

Y sidekiq.rb

Sidekiq.configure_server do |config| config.redis = { :url => ENV[''REDIS_URL''], :namespace => ''btsidekiq'' } if defined?(ActiveRecord::Base) config = Rails.application.config.database_configuration[Rails.env] config[''adapter''] = ''postgis'' config[''pool''] = ENV[''DB_POOL''] || 5 config[''reaping_frequency''] = ENV[''DB_REAP_FREQ''] || 10 # seconds ActiveRecord::Base.establish_connection(config) end end Sidekiq.configure_client do |config| config.redis = { :url => ENV[''REDIS_URL''], :namespace => ''btsidekiq'' } end

El tamaño de nuestro grupo de bases de datos es bastante grande DB_POOL = 100 y estamos en una base de datos PG que aparentemente soporta 500 conexiones al mismo tiempo.


Este error se debe a que su adaptador de postgis intenta usar una conexión obsoleta / muerta del grupo de conexión ActiveRecord. Hay dos formas de abordar este problema:

  1. Tamaño de su grupo de conexiones para que coincida con el número de hilos / proceso
  2. Baja frecuencia de cosecha de la conexión (Reaper verifica el conjunto en busca de conexiones muertas, cada N segundos)

Para implementar el número 1, debe configurar el tamaño de su grupo de manera adecuada para Unicorn y para Sidekiq, que probablemente tengan diferentes necesidades.

Unicornio es un solo hilo, por lo que el tamaño de grupo predeterminado de 5 conexiones por proceso es correcto para usted. Esto asignará hasta 5 conexiones para cada uno de los trabajadores WEB_CONCURRENCY backend de WEB_CONCURRENCY . Debe restablecer el tamaño de grupo predeterminado y usar su unicorn.rb existente:

$> heroku config:set DB_POOL=5

Sin embargo, Sidekiq utiliza un modelo muy diferente. Por defecto, Sidekiq tiene un proceso único y N hilos. Desea un tamaño de grupo de DB un poco más grande que el número de subprocesos de Sidekiq. Puede implementar esto en su config/initializers/sidekiq.rb siguiente manera:

Sidekiq.configure_server do |config| pool_size = Sidekiq.options[:concurrency] + 2 config.redis = { :url => ENV[''REDIS_URL''], :namespace => ''btsidekiq'', :size => pool_size } if defined?(ActiveRecord::Base) config = Rails.application.config.database_configuration[Rails.env] config[''adapter''] = ''postgis'' config[''pool''] = pool_size config[''reaping_frequency''] = ENV[''DB_REAP_FREQ''] || 10 # seconds ActiveRecord::Base.establish_connection(config) end end

Mi mejor conjetura es que al usar un grupo tan grande de 100 conexiones, es más probable que acumules conexiones muertas. El tamaño adecuado de la piscina debería solucionar este problema.

Si esto no funciona, debería intentar reducir su DB_REAP_FREQ a 5 segundos.