Verbindungs-pool-Problem mit ActiveRecord-Objekte in rufus-scheduler -
Ich bin mit rufus-scheduler zum ausführen einer Reihe von häufigen Aufträgen, die einige verschiedene Aufgaben mit ActiveRecord-Objekten. Wenn es irgendeine Art von Netzwerk-oder postgresql-Schluckauf, auch nach der Wiederherstellung alle threads werfen die folgende Fehlermeldung, bis der Prozess neu gestartet wird:
ActiveRecord::ConnectionTimeoutError (konnte nicht erhalten Sie eine Datenbank-Verbindung innerhalb von 5 Sekunden gewartet 5.000122687 Sekunden). Die max pool size ist derzeit 5; erhöhen Sie es.
Kann der Fehler leicht nachvollzogen werden, indem Neustart von postgres. Ich habe versucht zu spielen (bis zu 15) mit dem pool der Größe, aber kein Glück gibt.
Führt mich zu glauben, die verbindungen sind nur in einem veralteten Zustand, ich dachte, das wäre behoben, durch den Aufruf von clear_stale_cached_connections!
.
Ist es ein zuverlässiger Muster, dies zu tun?
Den block übergeben wird, ist eine einfache select-und update-aktiven Datensatz aufrufen, und geschieht, egal, was die AR-Objekt ist.
Den rufus job:
scheduler.every '5s' do
db do
DataFeed.update #standard AR select/update
end
end
wrapper:
def db(&block)
begin
ActiveRecord::Base.connection_pool.clear_stale_cached_connections!
#ActiveRecord::Base.establish_connection # this didn't help either way
yield block
rescue Exception => e
raise e
ensure
ActiveRecord::Base.connection.close if ActiveRecord::Base.connection
ActiveRecord::Base.clear_active_connections!
end
end
- alle update drauf?
- Ich bin auch vor demselben Problem, habe versucht, oben und schon
ActiveRecord::Base.connection_pool.with_connection
tun, aber nicht arbeiten
Du musst angemeldet sein, um einen Kommentar abzugeben.
Rufus-scheduler ein neuer thread für jeden job.
ActiveRecord auf der anderen Seite nicht teilen kann, verbindungen zwischen den threads, so muss es eine Verbindung zuweisen zu einem bestimmten thread.
Wenn Ihr thread doesn T haben eine Verbindung noch, es wird einer aus dem pool.
(Wenn alle verbindungen im pool verwendet werden, wird es warten, bis eines nach der Rückgabe aus einem anderen thread. Schließlich timing und werfen ConnectionTimeoutError)
Es ist Ihre Verantwortung, es wieder zurück an den pool, wenn Sie fertig sind, in eine Rails-app, dies erfolgt automatisch. Aber wenn Sie verwalten Ihre eigenen threads (wie rufus tut), müssen Sie dies selbst tun.
Lucklily, es gibt eine api für diese:
Wenn du deinen code in eine with_connection block, es wird eine Verbindung bilden den pool, und lassen Sie es, wenn es fertig ist
In Ihrem Fall:
Sollte den trick tun....
http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html#method-i-with_connection
Den Grund kann sein, dass du viele threads, die alle verbindungen, wenn
DataFeed.update
Methode nimmt mehr als 5 Sekunden, als Sie den block können überlappt werden.versuchen
Auch versuchen, Anschluss lösen anstatt es zu schließen, es.
Ich weiß nicht wirklich, was rufus-scheduler, aber ich habe einige Ideen.
Das erste problem, könnte ein bug auf rufus-scheduler, der nicht checkout Datenbank Verbindung richtig. Wenn es der Fall ist, die einzige Lösung ist das löschen veralteter verbindungen manuell als Sie bereits tun und zu informieren, wie der Autor rufus-scheduler zu Ihrem Problem.
Einem anderen problem, das passieren könnte, ist, dass Ihre DataFeed-Vorgang dauert eine wirklich lange Zeit, und da es erfolgt alle 5 Sekunden Schienen läuft die Datenbank-verbindungen, aber es ist eher unwahrscheinlich.