Django: CONN_MAX_AGE behält Verbindungen bei, verwendet sie jedoch nicht mit PostgreSQL

16

Ich habe ein Django-Setup, das Django 1.6.7 und Postgres 9.3 auf Ubuntu 14.04 LTS verwendet.

Zu jedem Zeitpunkt erhält die Site ungefähr 250 gleichzeitige Verbindungen zur PostgreSQL-Datenbank, einer Quad Core Xeon E5-2670 mit 2,5 GHz und 16 GB RAM. Die durchschnittliche Auslastung dieser Maschine liegt den ganzen Tag über zwischen 20 und 30.

Gelegentlich erhalte ich E-Mails, in denen ich darüber informiert werde, dass das Zeitlimit für Verbindungen zur Datenbank überschritten wurde, und ich schätze, dass das Aktivieren eines Verbindungspools dieses Problem mindert und die Datenbank ein wenig entlastet.

Da wir Django 1.6 verwenden, steht uns das eingebaute Pooling zur Verfügung. Wenn ich jedoch CONN_MAX_AGE auf 10 Sekunden oder 60 Sekunden setze, springt die Anzahl der gleichzeitigen Verbindungen fast sofort auf die maximal zulässige Einstellung (was ungefähr dem Doppelten entspricht, was wir normalerweise sehen), und Verbindungen werden abgewiesen.

Es scheint also, dass die Verbindungen aus irgendeinem Grund bestehen bleiben , aber NICHT wiederverwendet werden.

Woran könnte das liegen?

PS. Wir verwenden Gunicorn auch mit --worker-class = eventlet. Vielleicht ist dies die Quelle unserer Leiden?

synic
quelle

Antworten:

18

Beim Experimentieren stellte ich fest, dass die Ursache unseres Problems in der Tat Gunicorns Eventlet-Arbeiterklasse war. Jeder Mikrothread stellte seine eigene dauerhafte Verbindung her, und es gab überhaupt keine Möglichkeit, einen von ihnen wiederzuverwenden.

Das Deaktivieren von eventlet hat die Last auf unseren Webservern erhöht (aber nicht wesentlich), aber die Postgres-Last ist jetzt auf einen Durchschnitt von 3 gesunken. Von 30.

synic
quelle
2
Sie haben uns gerade eine Menge Zeit gespart! Wir beobachten genau das gleiche Verhalten und verwenden eventlet. Versucht, zum Verbindungspooling zu wechseln und zu sehen, wie es funktioniert.
Silentser
3
Update: Pooling von Datenbankverbindungen mit pgBouncer schien das Problem zu lösen (wir verwenden immer noch Eventlet)
Silentser
Anscheinend gibt es auch psycogreen: pypi.python.org/pypi/psycogreen/1.0 (Ich habe es nicht ausprobiert, als ich CONN_MAX_AGE auf Null gesetzt habe, benötigt unser System 20 ms, um eine DB-Verbindung herzustellen, sodass wir einfach kein Pooling benötigen.)
Darren
1
Es dauerte einige Zeit, bis ich googelte, um diese Antwort auf genau dasselbe Problem zu finden, das wir hatten.
Alper