详细摘要 摘要

生成:2025-06-21 18:32

摘要详情

音频文件
2020-09-09 | PyCon 2020 | "Taking Django's ORM Async" - Andrew Godwin
摘要类型
详细摘要
LLM 提供商
openai
LLM 模型
gemini-2.5-pro
温度
0.3
已创建
2025-06-21 18:32:38

概览/核心摘要 (Executive Summary)

在2020年PyCon Australia的一次演讲中,Django核心开发者Andrew Godwin详细阐述了为Django ORM引入异步支持的宏伟计划,这是继Django 3.1成功实现异步视图后的下一个关键步骤。该计划的核心目标并非将Django完全改造为异步框架,而是构建一个“混合”模式,允许开发者在同一个项目中同时使用同步和异步代码,以便仅在性能关键的I/O密集型场景(如数据库查询、外部API调用)中使用异步来提升效率。

Godwin提出了一个三阶段实施方案:首先,创建一个对用户友好的异步API(如aget(), acreate(), async for),其底层仍通过线程池执行同步的数据库操作,以便开发者能尽早使用并锁定API设计;其次,将异步支持深入到ORM的查询构造和编译器等内部核心逻辑;最后,实现对原生异步数据库驱动的支持,以获得最佳性能,尽管这依赖于第三方库的成熟度。

演讲强调了几个关键的技术挑战:
1. API命名空间:由于Python的语言设计,必须为异步操作提供独立的命名(如aget()),而不能简单地await现有方法。
2. 禁止隐式I/O:在异步模式下,将禁止通过属性访问懒加载关联对象(如my_obj.foreign_key),强制开发者使用select_related,这既是技术限制,也被认为是更优的编程实践。
3. 事务管理:跨越异步/同步边界时,保持事务的原子性是一个重大难题,因为事务与线程绑定的数据库连接紧密相关。

最终,该计划旨在让Django ORM在保持其安全、易用特性的同时,赋予开发者并行执行数据库查询的能力,从而显著提升应用的性能和响应速度。


背景与目标:迈向“混合”异步的Django

在Django 3.1成功发布并支持异步视图(Async Views)后,社区的下一个主要目标是为Django ORM(对象关系映射器)添加异步功能。Andrew Godwin强调,这一努力并非要将Django转变为一个纯异步框架,而是旨在创建一个“混合异步世界”(hybrid async world)。

  • 核心理念:允许同步代码和异步代码共存。开发者可以继续使用更简单、更直接的同步代码处理大部分业务逻辑,仅在性能瓶颈或涉及大量I/O等待(如数据库查询、HTTP请求)的部分采用异步模式。
  • 异步视图的成功:异步视图(async def)可以与同步视图(def)在同一个urls.py文件中无缝协作,这证明了混合模式的可行性和优势。
  • ORM的重要性:ORM是Django代码库中体量最大、最复杂的部分。为其添加异步支持是整个异步计划中最具挑战性但也最有价值的一步。

    “The rm is honestly most of Django. This is by lines of code. It's certainly by complexity and understanding. It is a big, hairy beast sitting the center of what we know and love.”

三阶段实施计划

Godwin提出了一个循序渐进的三阶段计划,以确保平稳过渡和逐步交付价值。

  • 第一阶段:实现异步用户接口 (Asynchronous User-Facing API)

    • 目标:为ORM的常用操作提供异步版本的API,如aget(), acreate(), aupdate()以及通过async for进行异步迭代。
    • 实现方式:在这一阶段,尽管API是异步的,但底层的数据库操作仍将通过Django内置的sync_to_async适配器在独立的线程中同步执行。
    • 优势:可以快速锁定API设计,让开发者能够开始编写和测试异步ORM代码,并立即从并行执行多个查询中获益,而无需等待底层数据库驱动的完全异步化。
  • 第二阶段:改造ORM核心逻辑 (Asynchronous Query Internals)

    • 目标:将异步支持深入到ORM的内部,包括查询(Query)的构建、编译和执行逻辑。
    • 实现方式:将异步与同步的边界从用户API层下推到数据库适配器层。这意味着从QuerySet到数据库连接的大部分路径都将是“异步友好”的。
    • 效果:进一步减少线程切换的开销,提升内部处理效率。
  • 第三阶段:原生异步数据库适配器 (Native Asynchronous Database Adapters)

    • 目标:利用原生的异步数据库驱动(如asyncpg)替换掉基于线程的同步驱动,实现端到端的全异步路径,以获得极致性能。
    • 挑战与依赖
      • 此阶段的实现不完全由Django团队控制,高度依赖于第三方异步数据库库的成熟度和可用性。
      • Python缺乏一个像同步DB-API 2那样的官方异步数据库API标准,导致各库实现不一,增加了适配难度。
    • 现实考量:Godwin明确指出,即使第三阶段无法对所有数据库后端完全实现,仅完成前两个阶段也能带来巨大的性能提升。基于线程的数据库访问“并非那么糟糕”(not terrible),对于大多数应用已经足够。

关键技术挑战与设计决策

将一个庞大且设计精良的同步API改造为支持异步,面临着诸多源于语言设计和框架历史的挑战。

  • API命名空间:为何需要 aget() 而非 await get()

    • 原因:Python的async def函数返回的是一个协程对象(coroutine),而普通函数返回实际结果。一个函数无法根据调用它的上下文(同步或异步)来决定返回类型。
    • 决策:为了避免破坏现有同步代码的兼容性,所有异步操作都必须拥有一个明确的、独立的名称。因此,Model.objects.get()的异步版本将被命名为Model.objects.aget()(或其他类似的命名,具体待定)。
    • 附带好处:这种明确的命名有助于代码审查,可以清晰地识别出代码中哪些是异步调用,防止因误用同步阻塞函数而导致的性能问题。
  • 禁止隐式I/O:强制使用 select_related

    • 问题:Django ORM允许通过属性访问来“懒加载”关联对象(例如 post.author.name)。在后台,如果author对象未被预加载,Django会发起一次新的数据库查询。在异步上下文中,这种隐式的、同步的I/O操作会阻塞整个事件循环。
    • 解决方案:在异步模式下,当尝试访问一个未通过select_relatedprefetch_related预先抓取的关联对象时,Django将直接抛出错误
    • 影响:这强制开发者在编写查询时就明确声明需要加载的数据,这本身就是一种被广泛推荐的最佳实践,有助于避免“N+1查询”问题。

      “...in asynchronous mode, you kind of have to select related. ... I think you'll find that being forced you [to use] select_related is probably a good thing.”

  • 异步迭代:async for 的优雅支持

    • 优势:Python为异步迭代提供了async for语法和__aiter__魔术方法,这与同步迭代的for__iter__形成了完美对应。
    • 实现:Django的QuerySet对象可以同时实现__iter____aiter__,使得在同步和异步代码中迭代查询结果集的写法非常相似和自然。
  • 事务管理的复杂性 (Transactions)

    • 核心难题:数据库事务通常与单个数据库连接(或游标)绑定,而这些连接在Django中是线程本地的(thread-local)。当代码从异步上下文切换到同步上下文(通过在新线程中运行)时,会丢失原始的事务状态。
    • 后果:标准的transaction.atomic装饰器/上下文管理器将无法跨越异步和同步的边界。
    • 待定方案:解决方案尚在探索中,可能需要引入一个专为异步设计的、新的事务API,或者找到一种在不同线程间传递事务状态的方法。这是当前API设计阶段最棘手的“症结”之一。

无需异步化的部分

演讲者明确指出,并非Django的所有部分都需要异步化。

  • Django Migrations:迁移操作是一次性的、在后台串行执行的任务,不需要异步带来的性能提升。
  • 模型字段的内部转换、数据库Introspection等:这些CPU密集型或非高频I/O操作同样无需改造。

结论与展望

为Django ORM引入异步支持是一项复杂但至关重要的工程。其最终目标是让开发者能够轻松编写出高性能的Web应用,尤其是在处理多个独立的、I/O密集型任务时,可以通过并行查询大幅缩短响应时间。

  • 核心价值:异步ORM的真正威力在于能够安全、便捷地并行执行数据库查询,这是Django异步化进程中最能体现价值的部分。
  • 后续步骤:当前的首要任务是敲定异步API的设计、解决事务管理的难题以及设计异步连接管理方案。
  • 时间表:Andrew Godwin表示,他“温和地期望”(soft aiming)能在Django 3.2版本中包含第一阶段的成果,但也强调这并非一个确定的承诺。

对该项目感兴趣的开发者被鼓励参与到Django官方论坛的讨论中,共同推动Django异步生态的发展。