标准答案

  1. WSGI 通常用线程或进程承载阻塞请求,代码和生态成熟。
  2. ASGI 可以承载 async handler、WebSocket 和异步生命周期,但阻塞代码仍会卡 worker 或事件循环。
  3. 部署时要明确 worker 类型、线程、进程、连接和超时配置。
  4. 不要只把函数声明为 async 就认为数据库和 HTTP 调用已经非阻塞。

题目解析

WSGI 以一次调用处理一个同步请求,传统 Django、Flask 和同步 ORM 可以自然运行;ASGI 以 scope、receive、send 描述连接生命周期,能够承载 async handler、WebSocket 和长连接。选择哪一个首先取决于应用是否真的需要异步 I/O 或 WebSocket,而不是因为 ASGI 的名字更新。

ASGI 只提供异步调用边界,不会把同步数据库驱动、文件操作或第三方 SDK 自动变成非阻塞操作。同步代码放进事件循环会阻塞同一 worker 的其他请求;如果必须使用同步库,应放到受控线程池,并把线程数、超时和下游连接数一起纳入容量预算。

验证部署时要同时看框架适配器、服务器 worker 类型、请求超时、WebSocket 关闭和后台任务生命周期。一个声明为 async 的接口,如果内部仍然串行等待同步 I/O,实际收益可能比稳定的 WSGI 多进程更差。

常见误区

  • 误区:把 async def 当作异步化的全部工作。改正:逐个检查数据库、HTTP、缓存和文件库是否提供真正的异步调用,阻塞部分放入有上限的执行器。
  • 误区:通过不断增加 WSGI worker 解决延迟。改正:先确认 CPU、线程、连接池和下游容量,避免 worker 数量把数据库连接推过上限。
  • 误区:只测试 WebSocket 建连,不测试半开连接、心跳、客户端断开和服务停机。改正:为连接设置生命周期、关闭处理和可观测指标。

作者信息