![flask、gunicorn(gevent)、sqlalchemy(postgresql):连接过多](https://linux22.com/image/750995/flask%E3%80%81gunicorn%EF%BC%88gevent%EF%BC%89%E3%80%81sqlalchemy%EF%BC%88postgresql%EF%BC%89%EF%BC%9A%E8%BF%9E%E6%8E%A5%E8%BF%87%E5%A4%9A.png)
我创建了Flask
WSGI 应用程序,用作gunicorn
WSGI 服务器,并PostgreSQL
通过Flask SQLAlchemy
扩展使用数据库。这些都托管在 上Heroku
。
gunicorn 配置
- 工人人数:2人;
- 工作者连接数:1024;
- 线程数:1;
- 工人阶级:gevent。
Heroku PostgreSQL 配置
- 最大连接数:20。
其余一切都使用默认配置。
我收到此错误:sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) FATAL: too many connections for role <id>
。显然,我超出了允许的数据库连接数。
我尝试了以下方法来修复它:
- 对于 SQLAlchemy 设置
poolclass
为NullPool
; - 对于 SQLAlchmey 设置
pool_recycle
为 2。即使超过 2 秒后连接数仍然相同; session.close()
和engine.dispose()
;- 工作者数量 - 2,工作者连接数量 - 9;
- 工作者数量 - 1,工作者连接数量 - 18;
- 工作者数量 - 1,工作者连接数量 - 10,SQLAlchemy
max_overflow = 0
,SQLALchmeypool_size = 10
(我收到此错误:)sqlalchemy.exc.TimeoutError: QueuePool limit of size 10 overflow 0 reached, connection timed out, timeout 30
。
这些都不起作用。即使使用最低的 gunicorn 配置(1 个工作器,18 个连接),我仍然会收到此错误。我真的开始不明白到底发生了什么。
我以为它是这样工作的:每个工作器都有自己的引擎实例,每个引擎都有自己的池大小。因此,如果有 2 个工作器具有引擎默认配置(池大小为 5),那么我们最多可以有 2 * 5 = 10 个 DB 连接。但看起来事实并非如此。
问题
- 如何修复这个错误?
- 池如何
SQLAlchemy
与工作者一起工作gevent
?即,如何计算最大数据库连接数? - 我应该如何正确配置它以使其按预期工作?
答案1
你提到:
worker connections = 1024
threads = 1
但是gevent
,工作连接的数量是同时运行的(异步)线程的总数。
因此,您尝试建立的workers * worker_connections
连接数肯定高于您可以维持的连接数(基于定义的pool_size
限制)postgres
。
从 Postgres 开始并向后工作:
- Postgres = 最多 20 个连接
- 实例 = 1(看起来像)?
gunicorn
进程 = 2worker_connections
= 10 = (20 / 2)pool_size + max_overflow
= 10 [同worker_connections
!]pool_size = 10, max_overflow=0
或您想要的任何组合- 溢出连接会尽快清理;pool_size 连接可以保留
worker_connections
并且pool_size+max_overflow
在线程之间共享,但不在进程之间共享。
请注意,一旦您添加另一个实例或任何与数据库对话的内容,它将使用那 20 个宝贵的 Postgres 连接中的 1 个(或更多),因此您需要进行相应的调整。