WSGI / ASGI / CGI / FastCGI / SCGI / NGINX — 彻底搞懂谁是谁
Python 社区的同步 Web 服务器与应用框架之间的接口协议,定义在 PEP 3333。
| 规定项 | 具体内容 |
|---|---|
| 调用方式 | 服务器调用一个可调用对象 application(environ, start_response),是同步调用——调用后阻塞等待返回 |
| environ 参数 | 一个字典,包含所有 HTTP 请求信息:请求方法、路径、Headers、Query String、服务器环境变量等(约 20+ 个标准 key) |
| start_response 参数 | 一个回调函数,应用用它来设置 HTTP 状态码和响应头:start_response('200 OK', [('Content-Type', 'text/html')]) |
| 返回值 | 返回一个可迭代的字节序列(yield 或列表),就是 HTTP 响应体 |
| 生命周期 | 一个请求 = 一次同步函数调用,处理完才返回。没有长连接、没有 WebSocket |
| 文件类型 | 可以返回 write() callable 或文件对象(用于大文件流式传输) |
async def,WSGI 服务器根本不会 await 它,协程会被当作普通生成器直接丢弃或报错。
| 服务器 | 特点 |
|---|---|
| Gunicorn | 最主流,pre-fork worker 模型,稳定可靠,配置丰富 |
| uWSGI | 性能极高,支持多种协议(WSGI/FastCGI/HTTP),但配置复杂 |
| mod_wsgi | Apache 的 WSGI 模块,嵌入 Apache 进程 |
| Waitress | 纯 Python,Windows 友好,适合小型项目 |
| CherryPy 内置 | CherryPy 自带的生产级 WSGI 服务器 |
Flask、Django(原生 WSGI)、Pyramid、Bottle 等。
WSGI 的异步继承者,由 Django 团队和 Uvicorn 团队联合设计。不仅支持 HTTP,还支持 WebSocket 和长连接。
| 规定项 | 具体内容 |
|---|---|
| 调用方式 | 服务器将请求以 async callable 方式调用:await application(scope, receive, send) |
| scope 参数 | 一个字典,包含连接类型和请求信息。scope["type"] 区分协议类型:"http" / "websocket" / "lifespan" |
| receive 参数 | 一个 async callable,应用调用 await receive() 获取事件(请求体、WebSocket 消息、连接断开等) |
| send 参数 | 一个 async callable,应用调用 await send({"type": "http.response.start", ...}) 发送响应头,再 await send({"type": "http.response.body", ...}) 发送响应体 |
| 协议类型 | 三个 scope type:http(HTTP 请求响应)、websocket(双向通信)、lifespan(应用启动/关闭生命周期) |
| 生命周期 | 每个连接是一个独立的 async context,不是一次函数调用就结束。WebSocket 可以保持长连接持续收发 |
| 向后兼容 | ASGI 服务器可以包装 WSGI 应用(通过 asgiref.wsgi.WsgiToAsgi 适配器) |
服务器 → 调 application(environ, start_response)
→ 返回 bytes(同步,一次性)
服务器 → await application(scope, receive, send)
→ 多次 send(异步,事件驱动)
| 服务器 | 特点 |
|---|---|
| Uvicorn | 最主流,基于 uvloop + httptools,极快,Starlette 团队出品 |
| Hypercorn | 支持 HTTP/2、WebSocket、HTTP Trailers,基于 h2 |
| Daphne | Django Channels 官方服务器,基于 Twisted |
| granian | Rust 实现,新兴高性能方案 |
FastAPI(基于 Starlette)、Django(通过 Channels 支持部分 ASGI)、Starlette、Quart(异步版 Flask)等。
最早的 Web 服务器与外部程序的接口协议。每个请求启动一个新进程,通过环境变量传入请求信息,通过 stdin/stdout 传数据。服务器(如 Apache)负责监听端口、解析 HTTP,然后 fork 进程执行 CGI 脚本。
CGI 的改进版:
实现:PHP-FPM(PHP 的 FastCGI 进程管理器)、uWSGI(同时支持 FastCGI 协议)、Spawn-FCGI
FastCGI 的简化版,协议更简单,但用得不多。scgi 是唯一的实现。
| 角色 | 对应 | 做什么 |
|---|---|---|
| 大堂接待员 | NGINX(反向代理) | 迎客、引导、简单事务 |
| 厨房内部传菜规则 | WSGI / ASGI | 厨师和传菜员之间的协作规范 |
| 厨师(做菜的人) | Flask / FastAPI | 真正的业务逻辑处理 |
| 厨房经理 | Gunicorn / Uvicorn | 分配工作、管理人手 |
浏览器 → NGINX (80/443) → Uvicorn (:8000) → FastAPI app
或
NGINX → Gunicorn (WSGI workers) → Django app
或
NGINX → Gunicorn (Uvicorn workers) → FastAPI app
FastAPI 是 ASGI 框架,Gunicorn 原生只懂 WSGI。直接 gunicorn main:app 会把 FastAPI 的 async 函数当同步函数调用,协程永远不会被 await,直接报错或返回错误结果。
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker
这样 Gunicorn 只负责进程管理(master 进程 + 4 个 worker 子进程),每个 worker 内部实际是 Uvicorn 在跑,走 ASGI 协议。