我正在用 Python 构建一个 Web 应用程序(使用 Flask)。我不打算使用 SQLAlchemy 或类似的 ORM 系统,而是直接使用 Psycopg2。
我应该为每个新请求打开一个新的数据库连接(然后关闭它)吗?或者我应该使用一些东西来汇集这些连接?
我正在用 Python 构建一个 Web 应用程序(使用 Flask)。我不打算使用 SQLAlchemy 或类似的 ORM 系统,而是直接使用 Psycopg2。
我应该为每个新请求打开一个新的数据库连接(然后关闭它)吗?或者我应该使用一些东西来汇集这些连接?
PgBouncer 对应用程序和服务器来说非常简洁和透明。
我们已经在生产中使用 PgBouncer 2 年了,没有一个问题。这是一个非常棒的 PostgreSQL 连接池。
是的,连接池会有所帮助,但是是的,您必须根据数据库上的负载来找出实时连接或池大小的正确数字。
from psycopg2.pool import SimpleConnectionPool
from contextlib import contextmanager
dbConnection = "dbname='dbname' user='postgres' host='localhost' password='postgres'"
# pool define with 10 live connections
connectionpool = SimpleConnectionPool(1,10,dsn=dbConnection)
@contextmanager
def getcursor():
con = connectionpool.getconn()
try:
yield con.cursor()
finally:
connectionpool.putconn(con)
def main_work():
try:
# with here will take care of put connection when its done
with getcursor() as cur:
cur.execute("select * from \"TableName\"")
result_set = cur.fetchall()
except Exception as e:
print "error in executing with exception: ", e
答案取决于将发生多少这样的请求以及在您的 Web 应用程序中同时发生多少?如果您希望您的 Web 应用程序忙于同时登录的 100 甚至 1000 名用户,那么连接池通常是一个更好的主意。如果您只是将其作为一个辅助项目并且期望少于几百个用户,您可能会逃脱没有汇集。
如果此应用程序要同时为多个客户端提供服务,我认为连接池是最好的选择。
在 Flask、FastAPI 和所有依赖于具有多个工作人员的 wsgi/asgi 专用服务器的环境中,池化似乎是完全不可能的。这种行为的原因很简单:您无法控制池和主线程/进程。池实例仅可用于为一组客户端服务的单个线程 - 因此仅适用于一个工作人员。任何其他工作人员都将获得它自己的池,因此不能共享已建立的连接。
从逻辑上讲,这也是不可能的,因为您无法使用 python (2.x - 3.8) 在多核环境中的线程/进程之间共享这些对象状态。