详细摘要 摘要
生成:2025-06-21 18:49摘要详情
- 音频文件
- 2022-10-17 | DjangoCon 2022 | Async Django: The practical guide you've been **awaiting** for.
- 摘要类型
- 详细摘要
- LLM 提供商
- openai
- LLM 模型
- gemini-2.5-pro
- 温度
- 0.3
- 已创建
- 2025-06-21 18:49:23
摘要内容
概览/核心摘要 (Executive Summary)
本次演讲由 Django Fellow Carlton Gibson 主讲,旨在为 Django 开发者提供一份关于异步(Async)编程的实用指南,强调开发者无需深入底层,即可利用其强大功能。演讲核心聚焦两大实用模式:1) 聚合视图 (Aggregating Views),一种无需引入 GraphQL 即可通过并发内部 API 请求优化性能的模式,其最大优势是可直接在现有 WSGI 应用中运行;2) 实时更新应用,通过对比轮询、长轮询、SSE 和 WebSockets 四种策略,展示了如何借助 Django Channels 实现从简单到复杂的实时功能。
演讲的关键建议是采取务实且渐进的异步迁移策略。对于后台任务,asyncio.create_task 因缺乏健壮性不如专用任务队列。部署上,推荐采用混合模式:核心应用继续使用成熟稳定的 WSGI,而将新的异步功能部署在独立的 ASGI 服务上,以隔离风险。最后,演讲者强调了对长连接和空闲超时进行彻底测试的重要性,并建议使用心跳机制来维持连接。
引言与背景
- 演讲者介绍: Carlton Gibson,Django Fellow 之一,负责 Django 框架的日常维护、安全问题处理和版本发布。他同时也是 Django Channels 等多个生态系统包的维护者。
- 演讲目的: 旨在消除社区对 Async Django 的困惑,通过实际案例展示如何在 Django 应用中务实地引入异步功能,而无需深入研究其复杂的底层实现。
Asyncio 核心概念入门
演讲首先通过一个简单的示例介绍了 Python 标准库 asyncio 的基本用法,它是 Django 异步支持的基础。
- 核心组件:
asyncio模块: Python 的标准异步运行时,提供事件循环 (Event Loop) 来调度并发任务。async def: 用于定义一个协程函数 (coroutine function)。调用它不会立即执行代码,而是返回一个协程对象 (coroutine object)。await: 用于暂停当前协程的执行,将控制权交还给事件循环,等待一个“可等待对象”(如另一个协程或 I/O 操作)完成。
- 关键函数:
asyncio.create_task(): 将一个协程作为任务安排到事件循环上并发执行,但它本身不处理错误或重试。asyncio.gather(): 等待多个任务全部完成。这是一个关键步骤,否则主函数会直接退出,导致后台任务被终止。
关键问题:Async 能否用于后台任务?
对于“能否使用 asyncio.create_task 来处理后台任务”这一常见问题,演讲者给出了一个审慎的回答:“可以,但这取决于情况 (it kind of, and it depends)”。
- 局限性 (Kind of):
asyncio.create_task本身不提供错误处理、状态跟踪或重试机制。对于需要高可靠性的任务,使用 Celery 或 Django-Q 等成熟的任务队列是更明智的选择。 - 依赖于运行方式 (It depends):
- WSGI (Web Server Gateway Interface): 在传统的 WSGI 模式下,当 Django 遇到一个
async def视图时,它会为该请求临时启动一个事件循环,视图返回响应后,事件循环立即关闭。 - ASGI (Asynchronous Server Gateway Interface): 在 ASGI 模式下,存在一个持续运行的事件循环。
- 结论: 在 WSGI 下,
async def视图可以正常工作,但通过create_task启动的任何后台任务都会在请求结束时被中断。只有在 ASGI 服务器(如 Daphne 或 Uvicorn)下,这些任务才能在主请求结束后继续执行。
- WSGI (Web Server Gateway Interface): 在传统的 WSGI 模式下,当 Django 遇到一个
实用模式一:聚合视图 (Aggregating Views)
这是一个演讲者高度推荐的模式,他称之为“我们在 GraphQL 出现之前就已经在做的事情”。
- 问题场景: 前端需要在一个页面上展示来自多个数据源的信息(如酒店详情及其房间列表),但不希望发起多次网络请求。
-
解决方案: 创建一个单一的
async def视图,使用httpx等异步库和asyncio.gather并发地请求应用内部的其他 API 端点,然后将结果组合成单一响应返回。```python
伪代码示例
import asyncio
import httpx
from django.http import JsonResponseasync def aggregated_view(request, hotel_id):
hotel_url = f"/api/hotels/{hotel_id}/"
rooms_url = f"/api/hotels/{hotel_id}/rooms/"async with httpx.AsyncClient() as client: tasks = [ client.get(request.build_absolute_uri(hotel_url)), client.get(request.build_absolute_uri(rooms_url)) ] hotel_resp, rooms_resp = await asyncio.gather(*tasks) response_data = { "hotel": hotel_resp.json(), "rooms": rooms_resp.json(), } return JsonResponse(response_data)```
-
核心优势:
- 无需改变部署架构: > “你可以立刻在你现有的 WSGI 应用中实现它……Django 会为这个聚合视图单独启动一个事件循环,而你应用的其他部分保持不变。”
- 性能提升: 将串行的网络请求变为并行,显著减少总响应时间。
实用模式二:构建实时更新的聊天应用
演讲通过一个聊天应用的例子,详细对比了四种实现“实时更新”的策略。当简单的轮询无法满足需求时,就需要引入 Django Channels 及其核心组件 Channel Layer 和 Consumers。
关键协作工具:sync_to_async / async_to_sync
在异步 Consumers 中与同步的 Django 组件(如 ORM 和模板引擎)交互时,必须使用转换函数。sync_to_async 是最常用的一个,它将一个阻塞的同步函数(如数据库查询 Message.objects.filter() 或模板渲染 render_to_string())包装起来,使其可以在不阻塞事件循环的情况下被 await。这是实现异步与同步代码无缝协作的关键。
四种实时更新策略对比
| 策略 | 实现方式 | 优点 | 缺点 | 适用场景/要求 |
|---|---|---|---|---|
| 轮询 (Polling) | 前端定时发起 HTTP 请求 | 实现最简单,兼容任何部署 | 扩展性差,延迟高,浪费资源 | 客户端少,实时性要求不高的内部系统 |
| 长轮询 (Long Polling) | 服务器保持请求开启,直到有新数据或超时 | 响应及时 | 仍有连接建立/销毁开销 | 需要实时推送,但为单向通信 |
| SSE (Server-Sent Events) | 服务器通过一个持久连接向客户端单向推送事件 | 高效,减少了连接开销 | 单向通信(服务器到客户端) | 比长轮询更优的单向实时数据流场景 |
| WebSockets | 建立持久的双向通信连接 | 功能最强大,支持双向实时通信 | 相对复杂,但生态成熟 | 聊天、在线协作、游戏等复杂实时应用 |
- 务实选择: 最终选择应基于具体需求。如果延迟要求不高,轮询即可。若需单向实时推送,SSE 是优选。若需双向通信,则必须使用 WebSockets。
部署与运维建议
演讲者强烈建议采取谨慎务实的部署策略,并指出异步生态尚未如 WSGI 那般成熟,WSGI 仍是许多生产环境的首选。
- 采用混合部署策略: > “将你的核心应用部署在 WSGI 上,就像你现在做的一样,然后只将你的异步代码放在一个旁路的 ASGI 应用中。” 这种渐进式迁移策略可以利用 WSGI 的稳定性和成熟生态,同时将新异步功能的风险隔离。
- 进行全面的端到端测试: 异步应用的问题常出自部署环境。必须彻底测试整个网络堆栈,包括负载均衡器(Load Balancer)对长连接的支持、Web 服务器的配置以及 WebSocket 升级是否正常。
- 警惕并解决空闲超时: 检查各层(负载均衡器、反向代理)的空闲连接超时(Idle Timeout)设置。一个常见的陷阱是,看似正常的连接因长时间无数据传输而被网络设备断开。
- 使用心跳机制 (Heartbeats): 为防止空闲连接被断开,可从服务器定期(如每 20 秒)发送一个小的“心跳”消息,以保持连接活跃。这能解决大量因超时引起的断连问题。
结论
Async Django 提供了强大的能力。演讲者鼓励开发者从低风险、高回报的模式(如聚合视图)开始尝试,逐步为应用添加更高级的实时功能,并享受探索异步编程的乐趣。
评审反馈
总体评价
总结内容整体质量较高,准确捕捉了演讲的核心技术要点和实用模式,结构清晰,语言专业。但仍存在少量事实性偏差和可优化之处。
具体问题及建议
- 事实准确性:关于WSGI/ASGI部署的表述存在偏差
-
修改建议:原文明确提到"Jango allows you to write async death functions, which will be run asynchronously with an event loop",但总结中"在WSGI下无法使用async功能"的表述过于绝对。应调整为"在WSGI下async视图会为每个请求临时创建事件循环,但无法支持持续后台任务"。
-
完整性:遗漏了重要技术细节
-
修改建议:应补充说明sync_to_async/async_to_sync这对关键工具函数的使用场景(如模板渲染需在同步线程执行),这是实现ORM与异步视图协作的重要机制。
-
格式规范:执行摘要部分过长
-
修改建议:将当前"概览/核心摘要"压缩50%,把技术细节移至后续对应章节。执行摘要应保持提纲挈领的特性。
-
内容组织:部署建议部分结构松散
-
修改建议:将混合部署、全面测试、心跳机制三点建议改为编号列表形式,并补充原文强调的"渐进式迁移"策略(先核心WSGI+旁路ASGI)。
-
语言表达:存在少量术语不统一
- 修改建议:统一术语使用,如原文使用"coroutine"而非"协程","channel layer"应保持英文不翻译。技术名词首次出现时应标注英文原文。
优化方向
-
增加技术决策树:针对四种实时更新方案(轮询/长轮询/SSE/WebSocket)制作对比表格,包含适用场景、复杂度、兼容性等维度。
-
强化实践指导:在聚合视图部分补充代码片段示例,展示httpx与asyncio.gather的具体用法。
-
突出风险提示:在部署章节更醒目地标注原文强调的"异步生态尚未完全成熟,WSGI仍是生产环境首选"这一核心观点。