13

I have a Django website with Postgresql backend, for which I'm utilizing pgbouncer for db connection pooling (transaction mode).

The application and the DB reside on separate servers (1 server each). I have installed pgbouncer on the application server. My question is: what should the config be in settings.py? Note that I'm using Unix sockets for connecting to pgbouncer.


My current settings.py contains:

DATABASE_URL = 'postgres://user1:pass1@xx.xxx.xxx.xxx:5432/db1'
DATABASES = {
'default': dj_database_url.config(default=DATABASE_URL)
}

Relevant sections of pgbouncer.ini are:

[databases]
db1 = host=xx.xxx.xxx.xxx port=5432 dbname=db1

listen_addr = *
listen_port = 6432
auth_type = md5
unix_socket_dir = /var/run/postgresql
pool_mode = transaction
max_client_conn = 200
default_pool_size = 300

userlist.txt contains:

"user1" "pass1"

Note: One answer is here, but doesn't work for me since the DB isn't available locally in my case. I need to set the DATABASE_URL environment variable, instead of using default = '...'.

One suggestions seems to be to treat pgbouncer as a database in settings.py. In that case, would something like the following work?

if PRODUCTION == '1':
    #PRODUCTION is set to '1' if in production environment
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'pgbouncer',
            'USER': 'user1',
            'PASSWORD': 'pass1',
            'HOST': '/var/run/postgresql',
            'PORT': '6432',
        }
Community
  • 1
  • 1
Hassan Baig
  • 15,055
  • 27
  • 102
  • 205
  • your question isn't clear. Are you having trouble connecting pgbouncer to postgresql or connecting django to pgbouncer? If it's the latter, you just treat pgbouncer as a database that's all – e4c5 Oct 26 '16 at 04:47
  • @e4c5: hey, how're you doing? Specifically, how should I connect to pgbouncer in `settings.py`? I'm adding a snippet of code in the question to illustrate how I think it should be done. You could help correct it? :-) – Hassan Baig Oct 26 '16 at 07:47
  • Shouldn't your engine be psycopg2 or postgis instead o – e4c5 Oct 26 '16 at 14:53
  • @e4c5: corrected. Have a look now. – Hassan Baig Oct 26 '16 at 15:55

2 Answers2

16

From the docs:

pgbouncer is a PostgreSQL connection pooler. Any target application can be connected to pgbouncer as if it were a PostgreSQL server, and pgbouncer will create a connection to the actual server, or it will reuse one of its existing connections.

Also,

Have your application (or the psql client) connect to pgbouncer instead of directly to PostgreSQL server.


The configurations:

pgbouncer.ini: An example pgbouncer.ini with comments about defaults

[databases]
db1 = host=xx.xxx.xxx.xxx port=5432 dbname=db1

[pgbouncer]
listen_addr = *
listen_port = 6432
auth_type = md5
auth_file = userlist.txt
unix_socket_dir = /var/run/postgresql
pool_mode = transaction
max_client_conn = 100
default_pool_size = 20

userlist.txt:

"user1" "pass1"

to put in settings.py:

if PRODUCTION == '1':
    #PRODUCTION is set to '1' if in production environment
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'db1',
            'USER': 'user1',
            'PASSWORD': 'pass1',
            'HOST': '/var/run/postgresql',
            # 'PORT': '6432',
        }

Extra:

In case not using unix socket - you can set HOST : '127.0.0.1' or 'localhost' if pgbouncer is running locally, or whatever the IP of server pgbouncer will be running on. From the docs:

If you’re using PostgreSQL, by default (empty HOST), the connection to the database is done through UNIX domain sockets (‘local’ lines in pg_hba.conf). If your UNIX domain socket is not in the standard location, use the same value of unix_socket_directory from postgresql.conf. If you want to connect through TCP sockets, set HOST to ‘localhost’ or ‘127.0.0.1’ (‘host’ lines in pg_hba.conf). On Windows, you should always define HOST, as UNIX domain sockets are not available.


In case of postgreSQL For ENGINE you can use postgresql or postgresql_psycopg2 - there's difference between the both given your Django version - postgresql_psycopg2 vs posgresql.

Nabeel Ahmed
  • 18,328
  • 4
  • 58
  • 63
  • 1
    And this answer saved my life again after all this time. I had included `'PORT': '6432'` in settings.py, I removed it as per this answer and voila! Could you explain why you commented this line? What's the significance? – Hassan Baig Sep 20 '17 at 13:06
  • default_pool_size should for sure be lower than max_client_conn in your pgbouncer.ini. Your default_pool_size is the amount of connections to your database from pgbouncer (per user. Most setups only has one). The default max connections for a postgresql database is 100. You need to leave a few of these connections for admin access etc, so default_pool_size should be max 95. but better set it at 20 or even less and let pgbouncer handle the pooling. – Christoffer May 21 '19 at 10:46
  • Thank you Christoffer for pointing this out, I have updated the values as per defaults. – Nabeel Ahmed Jun 14 '19 at 10:17
1

All of your DB settings in settings.py should be identical to the settings in your pgbouncer config, except the host in settings.py will point to pgbouncer. You probably need to change 'NAME': 'pgbouncer' to 'NAME': 'db1'. Since you're using a unix socket the port shouldn't matter.

Seán Hayes
  • 4,060
  • 4
  • 33
  • 48
  • Thanks for chiming in. Two clarifications: 1) shouldn't `NAME` include the name of the `pgbouncer` database (i.e. `pgbouncer`). Isn't the idea to connect to `pgbouncer` db in settings.py, and pgbouncer itself will do the rest? 2) I thought in our previous discussion, the consensus was *not to use unix sockets* since `pgbouncer` is installed on application server, and the DB server is separate? – Hassan Baig Oct 26 '16 at 19:48
  • You said pgbouncer is on your app server, so Django can connect to it using a unix socket. pgbouncer just can't use a unix socket to connect to your remote PG instance. `HOST` tells Django where to make the network connection (pgbouncer), `NAME` tells it which DB to connect to. Setting `'NAME': 'pgbouncer'` will cause pgbouncer to attempt to forward the query to the upstream PG instance and connect to a DB on that instance called `pgbouncer`, which probably isn't what you want. – Seán Hayes Oct 26 '16 at 20:21
  • It might be possible to configure different dbnames in `pgbouncer.ini` and `settings.py`, but I wouldn't recommend it, don't make things any more confusing. – Seán Hayes Oct 26 '16 at 20:23
  • Hmm, the app doesn't work when I try these settings. I can't see any errors, with even `debug = true`, nor is there anything in `/var/log/postgresql/pgbouncer.log`. Tried both unix socket and localhost. Any suggestion on where to start debugging this? – Hassan Baig Oct 30 '16 at 00:00
  • What do you mean by "doesn't work"? Is auth failing? Is the connection timing out? Does it hang forever? – Seán Hayes Oct 30 '16 at 21:24
  • That's the problem; I can't tell. My app just throws a `500` response, and nothing appears in `/var/log/postgresql/pgbouncer.log`. – Hassan Baig Nov 01 '16 at 18:52