繁体   English   中英

用于连接池的 FastAPI 数据库依赖设置

[英]FastAPI database dependency setup for connection pooling

考虑以下 fastapi 设置:

application.add_event_handler(
    "startup",
    create_start_app_handler(application, settings),
)

def create_start_app_handler(
    app: FastAPI,
    settings: AppSettings,
) -> Callable: 
    async def start_app() -> None:
        await connect_to_db(app, settings)
    return start_app

async def connect_to_db(app: FastAPI, settings: AppSettings) -> None:
    db_url = settings.DATABASE_URL
    engine = create_engine(db_url, pool_size=settings.POOL_SIZE, max_overflow=settings.MAX_OVERFLOW)

    SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
    db = SessionLocal()

    def close_db():
        db.close()
        engine.dispose()

    app.state.db = db
    app.state.close_db = close_db

close_db 用于在应用程序关闭时关闭数据库连接我定义了以下依赖项:

def _get_db(request: Request) -> Generator:
    yield request.app.state.db

def get_repository(
    repo_type: Type[BaseRepository],
) -> Callable[[Session], BaseRepository]:
    def _get_repo(
        sess: Session = Depends(_get_db),
    ) -> BaseRepository:
        return repo_type(sess)

    return _get_repo

这仍然允许我利用连接池吗?

此外,这感觉有点 hacky,如果有什么特别是我不应该做的,我可以使用一些反馈。

直言不讳; 对于文档中记录得很好的东西来说,它似乎过于复杂。

在您的情况下,您仅创建 1 个SessionLocal()实例并将在所有请求中共享该实例(因为您将其存储在app.state中)。 换句话说:不,这不会使用连接池,它只会使用 1 个连接。

更好的方法是通过中间件或依赖项为每个请求生成一个实例。 这样,当传入的请求被完全处理时,连接实际上是关闭的。 例如,像这样:

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/")
def root(db: SessionLocal = Depends(get_db)):
    return "hello world"

我不确定你是如何结束的,但我建议重构一堆。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM