2016-04-11 6 views
5

Ich stoße auf Probleme mit Sidekiq-Mitarbeitern.Wie Debuggen Rails Verbindung Pool-Verwendung?

ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds) 

Ich verfolge Empfehlungen über ActiveRecord::ConnectionTimeoutError und einen geeignet großen Verbindungspool verwenden.

Ich möchte herausfinden, ob ich den Verbindungspool erschöpft bin. Ich protokolliere size und connections.length von ActiveRecord::Base.connection_pool, aber sie bleiben bei einer konstanten Größe = 100 connections.length = 5. Das deutet darauf hin, dass dies kein Problem mit Ressourcenlecks ist.

Mein MySQL-Server ist so konfiguriert, dass bis zu 400 gleichzeitige Verbindungen möglich sind.

beendet Mein Job wie dieser aufzublicken:

class MyJob < ActiveJob::Base 
    queue_as :default  
    rescue_from StandardError do |exception| 
    # clear connections on exception. Not sure if this is a good idea or not. 
    ActiveRecord::Base.clear_active_connections!  
    end 

    def perform() 
    logger.info "size" 
    logger.info ActiveRecord::Base.connection_pool.instance_eval { @size } 
    logger.info "connections" 
    logger.info ActiveRecord::Base.connection_pool.instance_eval { @connections }.length 

    # Ensure connections come from connection pool. 
    ActiveRecord::Base.connection_pool.with_connection do |conn| 
     # do stuff 
    end 
    end 
end 

Ist dies der richtige Weg zu diagnostizieren, was dies verursacht, ob es Ressource Hunger oder Leckage ist? Gibt es andere Techniken, die ich verwenden kann, um herauszufinden, warum dies geschieht?

+0

Wie groß ist der Verbindungspool, der in Ihrer 'database.yml' definiert ist? Wie viele Sidekiq Worker-Threads verwenden Sie? – BoraMa

+0

Pool ist definiert als 100, wie in connection_pool.size, 25 Arbeiter gezeigt. – Joe

Antwort

2

Diese ActiveRecord::ConnectionTimeoutError kann meiner Meinung nach kommen nur in einem Szenario - wenn es so viele Threads wollen DB-Verbindungen verwenden, dass der Pool erschöpft ist und sogar für eine freie Verbindung warten hilft nicht (wie von dem source code gelernt).

In Ihrem Fall ist es seltsam. Sie verwenden nur 25 Worker-Threads, aber der Pool ist auf 100 Verbindungen eingestellt, daher gibt es genügend Reserve. Ich vermute immer noch, dass irgendwo Fäden spawnen müssen. Vielleicht tust du etwas in deinen Jobs? Vielleicht verwenden Sie einen Edelstein, der in Ihren Jobs Threads erzeugt?

Wie auch immer, wenn Sie in der Lage sind, die Ausnahme zu reproduzieren, würde ich vorschlagen, es zu fangen und die Liste aller Threads im Moment erhalten sie auftritt, so etwas wie dieses:

begin 
    # job stuff...  
rescue ActiveRecord::ConnectionTimeoutError 
    puts "listing #{Thread.list.count} threads:" 
    Thread.list.each_with_index do |t,i| 
    puts "---- thread #{i}: #{t.inspect}" 
    puts t.backtrace.take(5) 
    end 
end 

ich dort erwarten wird 100 oder mehr Threads und Sie sollten sehen, wo genau sie aus dem Backtrace stecken.

+0

Brilliant danke. Ich werde es versuchen. Ich spinne selbst keine Threads auf, aber wer weiß, was andere Bibliotheken tun! – Joe

+0

Haben Sie schon etwas gefunden? – BoraMa

+1

Nein. Ich reduzierte die Anzahl der Sidekiq Worker und habe keine Fehler. Dies wird in die Langzeituntersuchungsliste aufgenommen. Danke für das Kontrollieren. – Joe