2014-07-23 15 views
8

Ho un'app di rails ospitata con NGINX e Puma. Ogni 10 ore circa, l'app diventa inutilizzabile. Ogni volta che un utente tenta di connettersi, viene visualizzato il seguente messaggio di errore:Errore del pool di connessione del database di 4 rails

Error during failsafe response: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds) 

Continua fino al riavvio dell'app.

Ho letto che questo è dovuto al fatto che il pool di connessione del database è pieno e quindi è necessario creare dei thread nell'app rails che non chiudono la connessione al database al termine. Per quanto ne so, c'è solo un posto nel codice dell'app dove vengono utilizzati i thread: un blocco utilizza il modulo Ruby Timeout, ma questo non accede al database.

A seguito di questa guida https://devcenter.heroku.com/articles/concurrency-and-database-connections (non sto realtà usando Heroku) ho impostato la dimensione del pool di connessione al database a 5, con il seguente file di configurazione:

#config/initializers/database_connection.rb 
Rails.application.config.after_initialize do 
    ActiveRecord::Base.connection_pool.disconnect! 

    ActiveSupport.on_load(:active_record) do 
    config = ActiveRecord::Base.configurations[Rails.env] || 
       Rails.application.config.database_configuration[Rails.env] 
    config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10 # seconds 
    config['pool']    = ENV['MAX_THREADS'] || 5 
    ActiveRecord::Base.establish_connection(config) 
    end 

fine

Il il sito è ospitato utilizzando Rails 4.0.0. Ho letto che questo potrebbe in realtà essere un problema di Rails 4.0.0 e che questo è stato risolto nelle versioni successive, ma non sono sicuro di ciò. ConnectionTimeoutError on Heroku with Postgres

  1. C'è un modo per monitorare il numero di connessioni al database attivi nel pool di connessioni? Questo renderebbe il debug molto più facile.
  2. Si sta utilizzando il modulo Timeout all'interno del codice dell'app Rails probabile per la causa di questo problema?
  3. È probabile che si tratti di un problema di Rails 4.0.0 piuttosto che di un problema con la mia app?

L'app per binari è in esecuzione nell'ambiente di produzione. Posso dare maggiori informazioni sulla mia configurazione di Puma, NGINX se necessario.

+0

Ne vedo una tonnellata anche su un'app 4.1, che non ho mai visto su 3.x, quindi penso che il problema non sia stato risolto. – riffraff

+0

Qualcuno trova una soluzione per questo? Sto vedendo anche questo. Ho l'impressione che sia legato alla gemma 'airbrake' e/o usando' current_user' in 'application_controller.rb'. Qualcun altro che ha questo errore usando la gemma airbrake o usando current_user in application_controller.rb? – Catfish

+0

Commutando il mio server di sviluppo su webrick non vedo questo errore. Sto pensando che il colpevole sia il puma. – Catfish

risposta

0

Non penso che sia un problema di binari 4.0.0.

Così come indicato nel ruby timeout module documentation è deporre le uova un nuovo thread. Penso che ci sia una possibilità che possa generare un thread di lunga durata, mantenendo una connessione db live. Per controllare i thread in esecuzione è possibile utilizzare il metodo Thread.list. Tieni anche presente che la dimensione del tuo pool deve essere> = rispetto ai thread puma, moltiplicando i puma worker.

2

Il fatto che la risposta failsafe sta cercando di allocare una connessione al database può essere una pistola fumante. Potrebbe aiutarti a descrivere cosa succede nella risposta failsafe. La risposta failsafe è stata presumibilmente attivata quando la richiesta originale ha attivato un'eccezione. La routine show_exception delle rotaie che chiama la risposta failsafe viene chiamata dopo che ConnectionManager chiama clear_active_connections! per la richiesta corrente (che non è riuscita con un'eccezione), il che significa che i binari non rilasceranno automaticamente le connessioni al database dopo che la risposta failsafe ha avuto esito negativo. Ciò significa che il gestore della risposta failsafe è responsabile della pulizia delle proprie connessioni al database. Io non sono sicuro che sia buona pratica per il gestore risposta fail-safe si stia tentando di connettersi al database, ma se questo è il comportamento desiderato, quindi potrebbe essere necessario chiamare clear_active_connections! esplicitamente alla fine del tuo gestore failsafe (in un blocco di sicurezza).

Sto indagando un problema simile nel mio app e trovato questo per essere una guida utile per come il lavoro di connessioni: https://bibwild.wordpress.com/2014/07/17/activerecord-concurrency-in-rails4-avoid-leaked-connections/.Mentre il codice a cui si fa riferimento qui potrebbe richiedere alcune modifiche, c'è una buona idea di come rilevare quando si crea una connessione al database implicita.

Problemi correlati