flask、gunicorn(gevent)、sqlalchemy(postgresql):连接过多

flask、gunicorn(gevent)、sqlalchemy(postgresql):连接过多

我创建了FlaskWSGI 应用程序,用作gunicornWSGI 服务器,并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 设置poolclassNullPool
  • 对于 SQLAlchmey 设置pool_recycle为 2。即使超过 2 秒后连接数仍然相同;
  • session.close()engine.dispose();
  • 工作者数量 - 2,工作者连接数量 - 9;
  • 工作者数量 - 1,工作者连接数量 - 18;
  • 工作者数量 - 1,工作者连接数量 - 10,SQLAlchemy max_overflow = 0,SQLALchmey pool_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进程 = 2
  • worker_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 个(或更多),因此您需要进行相应的调整。

相关内容