使用pgbouncer时的Django设置

13

我有一个使用PostgreSQL作为后端的Django网站,正在利用pgbouncer进行数据库连接池管理(事务模式)。

应用程序和数据库驻留在不同的服务器上(每个服务器1个)。我已经在应用程序服务器上安装了pgbouncer。我的问题是:settings.py中应该配置什么?请注意,我使用Unix套接字连接到pgbouncer


我的当前settings.py内容如下:

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

pgbouncer.ini 相关部分为:

[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 包含:

"user1" "pass1"

注意: 这里有一个答案,但对于我的情况并不适用,因为在我这种情况下数据库不可在本地使用。我需要设置DATABASE_URL环境变量,而不是使用default = '...'

其中一个建议是将pgbouncer视为settings.py中的一个数据库。在这种情况下,是否像以下内容一样工作呢?

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',
        }

你的问题不太清楚。你是在连接Pgbouncer和PostgreSQL方面遇到了麻烦,还是在连接Django和Pgbouncer方面遇到了麻烦?如果是后者,你只需要将Pgbouncer视为一个数据库即可。 - e4c5
@e4c5:嘿,你好吗?具体来说,我应该如何在settings.py中连接到pgbouncer?我将在问题中添加一段代码片段以说明我认为应该这样做。你能帮忙纠正一下吗? :-) - Hassan Baig
你的引擎不应该是psycopg2或postgis吗? - e4c5
@e4c5:已修正。请再查看一下。 - Hassan Baig
2个回答

16

文档中得知:

pgbouncer是一个PostgreSQL连接池。任何目标应用程序都可以像连接到PostgreSQL服务器一样连接到pgbouncer,pgbouncer将创建一个到实际服务器的连接,或者它将重复使用其现有的连接。

此外,

让您的应用程序(或psql客户端)直接连接到pgbouncer而非PostgreSQL服务器。


配置文件:

pgbouncer.ini: 一个带有默认值注释的示例pgbouncer.ini

[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"

需要将以下内容放入 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',
        }

额外信息:

如果不使用Unix套接字 - 您可以将HOST设置为'127.0.0.1'或'localhost'(如果pgbouncer在本地运行),或者是pgbouncer服务器将要运行的IP地址。详情请参阅文档

如果您正在使用PostgreSQL,则默认情况下(HOST为空),与数据库的连接是通过UNIX域套接字(pg_hba.conf中的“local”行)完成的。如果您的UNIX域套接字不在标准位置,请使用与postgresql.conf中的unix_socket_directory相同的值。如果要通过TCP套接字连接,请将HOST设置为“localhost”或“127.0.0.1”(pg_hba.conf中的“host”行)。在Windows上,您应始终定义HOST,因为UNIX域套接字不可用。


对于postgreSQL而言,您可以使用ENGINE来选择postgresqlpostgresql_psycopg2 - 根据您的Django版本,两者之间存在区别 - 请查看postgresql_psycopg2 vs posgresql


1
这个答案再次拯救了我的生命。很久以前我在settings.py中包含了 'PORT': '6432',但是根据这个答案的建议我将其删除了,结果一切正常!您能解释一下为什么要注释掉这行代码吗?它有什么重要性吗? - Hassan Baig
在您的pgbouncer.ini中,default_pool_size应该比max_client_conn低。您的default_pool_size是从pgbouncer到数据库的连接数量(每个用户)。大多数设置只有一个用户。PostgreSQL数据库的默认最大连接数为100。您需要留下一些连接供管理员访问等,因此default_pool_size应该最多为95。但最好将其设置为20甚至更少,并让pgbouncer处理池化。 - Christoffer
感谢Christoffer指出这一点,我已根据默认值更新了数值。 - Nabeel Ahmed

1

您在settings.py中的所有DB设置都应该与pgbouncer配置中的设置相同,除了settings.py中的主机将指向pgbouncer。您可能需要将'NAME': 'pgbouncer'更改为'NAME': 'db1'。由于您正在使用unix套接字,因此端口不重要。


感谢您的参与。两个澄清:1)NAME不应该包括pgbouncer数据库的名称(即pgbouncer)。难道不是在settings.py中连接到pgbouncer数据库,然后由pgbouncer自己完成其余工作的想法吗?2)我记得在我们之前的讨论中,共识是不使用unix套接字,因为pgbouncer安装在应用程序服务器上,而DB服务器是分开的? - Hassan Baig
你说pgbouncer在你的应用服务器上,所以Django可以使用Unix套接字连接到它。但是pgbouncer无法使用Unix套接字连接到远程PG实例。HOST告诉Django在哪里建立网络连接(pgbouncer),NAME告诉它要连接哪个数据库。将'NAME': 'pgbouncer'设置为会导致pgbouncer尝试将查询转发到上游PG实例并连接到该实例上名为pgbouncer的数据库,这可能不是您想要的。 - Seán Hayes
可能可以在 pgbouncer.inisettings.py 中配置不同的数据库名称,但我不建议这样做,不要让事情变得更加混乱。 - Seán Hayes
哎呀,当我尝试这些设置时,应用程序无法正常工作。即使使用 debug = true,我也看不到任何错误,/var/log/postgresql/pgbouncer.log 中也没有任何信息。已经尝试了 unix socket 和 localhost 两种方式。有什么建议可以帮助我开始调试吗? - Hassan Baig
什么是“不起作用”?是否身份验证失败?连接超时了吗?它是否永远挂起? - Seán Hayes
那就是问题所在,我无法判断。我的应用程序只会抛出一个 500 响应,而 /var/log/postgresql/pgbouncer.log 中没有任何内容。 - Hassan Baig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接