FastAPI 生命周期事件详解:优雅管理应用启动与关闭

FastAPI 生命周期事件详解:优雅管理应用启动与关闭

fastapi FastAPI framework, high performance, easy to learn, fast to code, ready for production fastapi 项目地址: https://gitcode.com/gh_mirrors/fa/fastapi

什么是生命周期事件

在 FastAPI 应用中,生命周期事件指的是应用启动前和关闭时需要执行的特定逻辑。这些逻辑通常包括:

  • 应用启动前:初始化数据库连接池、加载机器学习模型等耗时操作
  • 应用关闭时:释放资源、保存状态、关闭连接等清理工作

为什么需要生命周期事件

考虑以下典型场景:

  1. 机器学习模型加载:一个大型模型加载可能需要数秒甚至更长时间,如果在每次请求时都加载,性能将无法接受
  2. 数据库连接池:应用启动时建立连接池,所有请求共享,而不是每个请求都新建连接
  3. 资源释放:应用关闭时需要确保GPU内存、文件句柄等资源被正确释放

现代推荐方案:lifespan 参数

FastAPI 推荐使用 lifespan 参数来管理生命周期,这是一个异步上下文管理器模式。

基础示例

from contextlib import asynccontextmanager
from fastapi import FastAPI

# 模拟机器学习模型
fake_database = {}

@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动时加载模型
    fake_database["model"] = lambda x: x * 2  # 简单示例模型
    yield
    # 关闭时清理资源
    fake_database.clear()

app = FastAPI(lifespan=lifespan)

@app.get("/predict")
async def predict(x: int):
    return {"result": fake_database["model"](x)}

关键点解析

  1. @asynccontextmanager:将普通函数转换为异步上下文管理器
  2. yield 语句:分隔启动逻辑和关闭逻辑
  3. 资源共享fake_database 被所有请求共享,避免重复加载

传统方案(已弃用)

虽然仍可使用,但不推荐在新项目中使用以下方式:

启动事件

app = FastAPI()

@app.on_event("startup")
async def startup_event():
    app.state.model = lambda x: x * 2

关闭事件

@app.on_event("shutdown")
def shutdown_event():
    with open("log.txt", mode="a") as log:
        log.write("Application shutdown")

为什么不推荐

  1. 启动和关闭逻辑分离,难以共享状态
  2. 不如 lifespan 方案直观和结构化
  3. 未来版本可能会移除

实际开发建议

  1. 资源初始化:将数据库连接池、模型加载等耗时操作放在 yield
  2. 资源释放:文件关闭、连接池清理等放在 yield
  3. 错误处理:考虑在 lifespan 中添加异常处理逻辑
  4. 测试考虑:生命周期事件不会在简单测试中触发,需要专门测试

高级用法

对于复杂场景,可以在 lifespan 中管理多个资源:

@asynccontextmanager
async def complex_lifespan(app: FastAPI):
    # 初始化多个资源
    db_pool = await create_db_pool()
    ml_model = load_ml_model()
    cache = setup_redis()
    
    # 将资源存入app状态
    app.state.db = db_pool
    app.state.model = ml_model
    app.state.cache = cache
    
    yield
    
    # 清理资源
    await db_pool.close()
    ml_model.unload()
    await cache.disconnect()

注意事项

  1. 子应用限制:生命周期事件不会在挂载的子应用中触发
  2. 异步兼容:确保资源管理与FastAPI的异步特性兼容
  3. 执行顺序:多个 lifespan 管理器的执行顺序可能影响初始化

通过合理使用生命周期事件,可以显著提升FastAPI应用的性能和可靠性,特别是在资源密集型场景下。

fastapi FastAPI framework, high performance, easy to learn, fast to code, ready for production fastapi 项目地址: https://gitcode.com/gh_mirrors/fa/fastapi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

### FastAPI 中 `lifespan` 功能详解 #### 一、功能概述 FastAPI 提供了一个名为 `lifespan` 的参数用于定义应用程序生命周期中的事件处理函数。这些事件主要分为启动前(`startup`)和关闭后(`shutdown`)两类,在应用初始化之前以及结束之后执行相应的逻辑操作[^2]。 #### 二、具体实现方式 通过装饰器或者直接传递给 FastAPI 实例化对象来指定 `lifespan` 函数。此函数应该是一个异步上下文管理器 (`@asynccontextmanager`),它允许开发者在其中编写启动时建立资源(比如数据库连接),并在程序终止时释放这些资源的代码片段。 ```python from contextlib import asynccontextmanager from fastapi import FastAPI # 假设这里有一个数据库模块db.py提供了database对象 from db import database @asynccontextmanager async def manage_database(app: FastAPI): await database.connect() try: yield finally: await database.disconnect() app = FastAPI(lifespan=manage_database) ``` 上述代码展示了如何利用 `lifespan` 参数配合自定义的异步上下文管理器来进行数据库连接池的创建销毁工作。 #### 三、官方文档示例解析 根据官方给出的例子可以更清晰地理解其应用场景: 当集成 Tortoise ORM 或其他第三方库时,可能需要确保每次请求都能访问到有效的会话/事务环境;而使用 `lifespan` 就能很好地解决这个问题——即可以在服务启动之初就准备好必要的依赖项,并于停止之时清理它们[^3]。 对于 MongoDB 连接而言,则可以通过类似的方式完成同样的目标: ```python from motor.motor_asyncio import AsyncIOMotorClient from fastapi import FastAPI class MongoConnectionManager: def __init__(self, uri: str): self.uri = uri self.client = None async def startup(self): self.client = AsyncIOMotorClient(self.uri) async def shutdown(self): self.client.close() mongo_manager = MongoConnectionManager('mongodb://localhost:27017') @app.on_event("startup") async def start_mongo(): await mongo_manager.startup() @app.on_event("shutdown") async def stop_mongo(): await mongo_manager.shutdown() ``` 这段代码实现了基于 `on_event()` 方法的手动注册启动关闭回调的效果,虽然不是严格意义上的 `lifespan` 用法,但在某些情况下也能达到相同的目的[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

滕璇萱Russell

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值