Skip to content

事件与生命周期

lifespan 事件、启动/关闭钩子、应用状态、发布订阅。

Updated View as Markdown
For humans

事件与生命周期

应用生命周期管理的核心问题:资源什么时候创建、什么时候销毁(连接池、配置、后台任务)。FastAPI 用 lifespan 统一管理,事件模式则解决组件间的解耦通知。

FastAPI 的 lifespan

from contextlib import asynccontextmanager

@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动时: 创建连接池、加载模型、启动后台任务
    app.state.pool = await create_pool()
    yield
    # 关闭时: 释放连接池、停止任务
    await app.state.pool.close()

app = FastAPI(lifespan=lifespan)
  • 启动钩子yield 之前执行,应用开始接收请求前完成
  • 关闭钩子yield 之后执行,进程退出时清理
  • 替代了旧的 @app.on_event("startup"/"shutdown")(已废弃),lifespan 是上下文管理器,异常处理更清晰
  • 共享状态放 app.state,处理器和依赖通过 request.app.state 访问

资源生命周期全景

资源 创建时机 销毁时机
配置读取 模块加载 / lifespan 进程结束
数据库连接池 lifespan 启动 lifespan 关闭
数据库会话 每次请求(依赖) 请求结束(yield)
后台任务(定时器) lifespan 启动 lifespan 关闭

分层记忆:进程级(lifespan)→ 请求级(依赖)→ 函数级(上下文管理器),每层的资源在对应层创建和释放。

事件模式(发布订阅)

事件驱动的本意:生产者和消费者解耦,不直接调用

from collections import defaultdict
from dataclasses import dataclass, field
from typing import Callable

class EventBus:
    def __init__(self):
        self._handlers: dict[str, list[Callable]] = defaultdict(list)

    def on(self, event: str, handler: Callable):
        self._handlers[event].append(handler)

    def emit(self, event: str, payload=None):
        for handler in self._handlers[event]:
            handler(payload)

bus = EventBus()
bus.on("order.created", send_notification)   # 下单后通知
bus.on("order.created", update_inventory)    # 同一事件多个订阅者

价值:订单服务不用知道谁关心“下单”这件事,新增订阅者不改发布方代码(开闭原则)。Python 里事件总线也可以用回调、信号库(blinker)实现。

注意边界:进程内事件用 EventBus;跨服务事件用消息队列(Kafka/RabbitMQ),事件总线不是分布式方案。

与 Java 对比

维度 Python/FastAPI Spring
生命周期 lifespan 上下文管理器 @PostConstruct/@PreDestroy、ApplicationListener
事件 EventBus / blinker ApplicationEventPublisher
异步 asyncio 原生 @Async + 线程池

面试追问

  1. lifespan 解决什么? 资源创建和销毁的时机管理:启动建连接池,关闭释放。上下文管理器保证异常时也执行清理
  2. startup 事件为什么废弃? on_event 生命周期语义弱(重复注册、无清理保证)。lifespan 是标准上下文管理器
  3. app.state 干什么? 存应用级共享状态(连接池、配置),处理器通过 request.app.state 访问
  4. 事件模式的价值? 发布者和订阅者解耦,新增订阅不改发布方。进程内用 EventBus,跨服务用 MQ
  5. 三层资源生命周期? 进程级 lifespan、请求级依赖、函数级上下文管理器,各层资源各层释放
Navigation

Type to search…

↑↓ navigate↵ selectEsc close