whitenoise postgres djangowhitenoise django connection-pooling pgbouncer

django - postgres - heroku python



Configuraciones ideales para pgbouncer con CONN_MAX_AGE de Django (1)

Estoy ejecutando un sitio web multi-tennant, donde me gustaría reducir la sobrecarga de crear una conexión PostgreSQL por solicitud. ConN_MAX_AGE de Django permite esto, a costa de crear una gran cantidad de conexiones inactivas abiertas para PostgreSQL (8 trabajadores * 20 subprocesos = 160 conexiones). Con 10MB por conexión, esto consume mucha memoria.

El objetivo principal es reducir la sobrecarga de tiempo de conexión. De ahí mis preguntas:

Configuraciones de Django 1.6:

DATABASES[''default''] = { ''ENGINE'': ''django.db.backends.postgresql_psycopg2'', .... ''PORT'': ''6432'' ''OPTIONS'': {''autocommit'': True,}, ''CONN_MAX_AGE'': 300, } ATOMIC_REQUESTS = False # default

Postgres:

max_connections = 100

PgBouncer:

pool_mode = session # Can this be transaction? max_client_conn = 400 # Should this match postgres max_connections? default_pool_size = 20 reserve_pool_size = 5


Aquí hay una configuración que he usado.

pgbouncer corriendo en la misma máquina que Gunicorn, apio, etc.

pgbouncer.ini:

[databases] <dbname> = host=<dbhost> port=<dbport> dbname=<dbname> [pgbouncer] : your app will need filesystem permissions to this unix socket unix_socket_dir = /var/run/postgresql ; you''ll need to configure this file with username/password pairs you plan on ; connecting with. auth_file = /etc/pgbouncer/userlist.txt ; "session" resulted in atrocious performance for us. I think ; "statement" prevents transactions from working. pool_mode = transaction ; you''ll probably want to change default_pool_size. take the max number of ; connections for your postgresql server, and divide that by the number of ; pgbouncer instances that will be conecting to it, then subtract a few ; connections so you can still connect to PG as an admin if something goes wrong. ; you may then need to adjust min_pool_size and reserve_pool_size accordingly. default_pool_size = 50 min_pool_size = 10 reserve_pool_size = 10 reserve_pool_timeout = 2 ; I was using gunicorn + eventlet, which is why this is so high. It ; needs to be high enough to accommodate all the persistent connections we''re ; going to allow from Django & other apps. max_client_conn = 1000 ...

/etc/pgbouncer/userlist.txt:

"<dbuser>" "<dbpassword>"

Django settings.py:

... DATABASES = { ''default'': { ''ENGINE'': ''django.contrib.gis.db.backends.postgresql_psycopg2'', ''NAME'': ''<dbname>'', ''USER'': ''<dbuser>'', ''PASSWORD'': ''<dbpassword>'', ''HOST'': ''/var/run/postgresql'', ''PORT'': '''', ''CONN_MAX_AGE'': None, # Set to None for persistent connections } } ...

Si recuerdo correctamente, básicamente puedes tener cualquier número de conexiones "persistentes" con pgbouncer, ya que pgbouncer libera las conexiones del servidor a la agrupación cuando Django termina con ellas (siempre y cuando pool_mode transaction o la statement para pool_mode ). Cuando Django intenta reutilizar su conexión persistente, pgbouncer se encarga de esperar una conexión utilizable a Postgres.