Подтвердить что ты не робот

Идеальные настройки для pgbouncer с Django CONN_MAX_AGE

У меня работает многотеновый сайт, где я хотел бы уменьшить накладные расходы на создание соединения PostgreSQL для каждого запроса. Django CONN_MAX_AGE позволяет это за счет создания большого количества открытых простоя подключений к PostgreSQL (8 рабочих * 20 потоков = 160 соединений). С 10 МБ на соединение это потребляет много памяти.

Основная цель - сократить накладные расходы времени соединения. Отсюда мои вопросы:

  • Какую настройку следует использовать для такого решения? (PgBouncer?)
  • Можно ли использовать режим пула транзакций с Django?
  • Было бы лучше использовать что-то вроде https://github.com/kennethreitz/django-postgrespool вместо пула Django?

Настройки 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
4b9b3361

Ответ 1

Вот настройка, которую я использовал.

pgbouncer работает на той же машине, что и пулемет, сельдерей и т.д.

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
    }
}
...

Если я правильно помню, вы можете в принципе иметь любое количество "постоянных" подключений к pgbouncer, поскольку pgbouncer освобождает серверные соединения обратно в пул, когда Django выполняется с ними (пока вы используете transaction или statement для pool_mode). Когда Django пытается повторно использовать свое постоянное соединение, pgbouncer заботится о том, чтобы ждать использования подключаемого Postgres.