Django应用PostgreSQL连接数耗尽问题排查及优化求助
问题分析与解决方案
1. conn_max_age 参数的作用
conn_max_age是Django数据库连接池的连接复用时长,单位为秒。设置成600意味着Django会把已建立的数据库连接保留10分钟,后续请求优先复用这些连接,避免重复创建连接的开销,以此提升性能。
但要注意:每个Daphne进程都会维护独立的连接池。你运行了3个Daphne进程,每个进程在处理请求时会创建多个连接并保留10分钟,当累计连接数超过PostgreSQL的max_connections配置上限时,就会触发"too many clients already"错误。
2. 错误成因
核心原因:连接池配置与进程数不匹配
PostgreSQL默认的max_connections通常在100左右(可通过执行SHOW max_connections;查看具体值)。3个Daphne进程各自维护连接池,加上连接被长时间保留,很容易把数据库的可用连接耗尽。
无异常流量也触发的原因
这不是恶意活动导致的,就是配置问题引发的连接堆积:
- 即使请求量稳定,每个新请求可能创建新连接,旧连接还没到
conn_max_age的回收时间,会持续占用连接数 - Daphne作为ASGI服务器,请求处理模式和WSGI不同,闲置连接更难被及时回收,时间一长就会堆积到上限
3. 连接泄漏排查方法
步骤1:查看当前数据库连接状态
在PostgreSQL中执行以下SQL,查看所有活跃连接的来源、状态和生命周期:
SELECT pid, usename, client_addr, application_name, state, query_start FROM pg_stat_activity;
如果看到大量来自你的Django应用(application_name一般是django)的idle状态连接,且持续时间超过conn_max_age设置的值,说明连接没有被正确回收,存在泄漏。
步骤2:检查代码中的连接使用
- 确保所有数据库操作都在请求生命周期内完成,不要在后台任务或异步函数中长时间持有连接
- 检查是否滥用
connection.close()手动关闭连接,导致连接管理异常 - 排查是否有长时间运行的视图或异步任务,这类任务会一直占用连接直到结束
步骤3:追踪连接的创建与关闭
在Django的settings.py中添加连接日志配置,观察连接的生命周期:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': {'class': 'logging.StreamHandler'}, }, 'loggers': { 'django.db.backends': { 'level': 'DEBUG', 'handlers': ['console'], }, } }
启动应用后,查看日志中连接的创建和关闭记录,判断是否存在只创建不关闭的情况。
4. 优化解决方案
你提到的移除conn_max_age或降低数值是有效的,还可以更精准地调整:
- 降低
conn_max_age:比如设为60(1分钟),让闲置连接更快被回收,减少堆积 - 限制单进程连接数:Django 3.1+支持设置
MAX_CONNS,控制每个进程的最大连接数:DATABASES = { "default": { **dj_database_url.parse(os.environ.get("DATABASE_URL", False), conn_max_age=60), "ATOMIC_REQUESTS": True, "OPTIONS": { "MAX_CONNS": 10, # 每个进程最多使用10个连接 } } } - 调整PostgreSQL配置:如果服务器资源充足,可以适当提高
max_connections值,但要注意连接数越多,PostgreSQL的内存消耗越高
内容的提问来源于stack exchange,提问作者Samuele B.
相关产品推荐
相关产品推荐

