Python Web 服务器协议体系详解

WSGI / ASGI / CGI / FastCGI / SCGI / NGINX — 彻底搞懂谁是谁

架构总览 Python Web 服务器协议体系全图

Python Web 服务器协议体系 Python Web 服务器协议体系 Client (浏览器) NGINX (反向代理 / 静态服务) 处理 SSL、负载均衡、静态文件 WSGI 协议 (同步) PEP 3333 — 同步调用约定 Gunicorn uWSGI Flask / Django 同步框架 ASGI 协议 (异步) 异步全协议 — HTTP/WebSocket 等 Uvicorn Hypercorn FastAPI / Starlette 异步框架 Gunicorn + Uvicorn workers Gunicorn 做进程管理,Uvicorn 做异步处理 生产环境常见方案 更早的协议:CGI / FastCGI / SCGI

WSGI Web Server Gateway Interface

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 它,协程会被当作普通生成器直接丢弃或报错。

实现 WSGI 协议的服务器

服务器特点
Gunicorn最主流,pre-fork worker 模型,稳定可靠,配置丰富
uWSGI性能极高,支持多种协议(WSGI/FastCGI/HTTP),但配置复杂
mod_wsgiApache 的 WSGI 模块,嵌入 Apache 进程
Waitress纯 Python,Windows 友好,适合小型项目
CherryPy 内置CherryPy 自带的生产级 WSGI 服务器

适配 WSGI 的框架

Flask、Django(原生 WSGI)、Pyramid、Bottle 等。

ASGI Asynchronous Server Gateway Interface

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 适配器)

WSGI vs ASGI 核心区别

WSGI

服务器 → 调 application(environ, start_response)
→ 返回 bytes(同步,一次性)

ASGI

服务器 → await application(scope, receive, send)
→ 多次 send(异步,事件驱动)

实现 ASGI 协议的服务器

服务器特点
Uvicorn最主流,基于 uvloop + httptools,极快,Starlette 团队出品
Hypercorn支持 HTTP/2、WebSocket、HTTP Trailers,基于 h2
DaphneDjango Channels 官方服务器,基于 Twisted
granianRust 实现,新兴高性能方案

适配 ASGI 的框架

FastAPI(基于 Starlette)、Django(通过 Channels 支持部分 ASGI)、Starlette、Quart(异步版 Flask)等。

历史协议 CGI / FastCGI / SCGI

CGI — Common Gateway Interface(1993)

最早的 Web 服务器与外部程序的接口协议。每个请求启动一个新进程,通过环境变量传入请求信息,通过 stdin/stdout 传数据。服务器(如 Apache)负责监听端口、解析 HTTP,然后 fork 进程执行 CGI 脚本。

致命问题:每个请求一个进程,启动开销巨大。10 个并发 = 10 个进程,性能灾难。

FastCGI(1996)

CGI 的改进版:

实现:PHP-FPM(PHP 的 FastCGI 进程管理器)、uWSGI(同时支持 FastCGI 协议)、Spawn-FCGI

SCGI — Simple CGI(2001)

FastCGI 的简化版,协议更简单,但用得不多。scgi 是唯一的实现。

演进时间线

1993
CGI
每请求 fork,极慢
1996
FastCGI
进程常驻,快
2003
WSGI
同步 Python 标准化
2016
ASGI
异步 Python 高性能

NGINX NGINX 和这些协议的关系

NGINX 不实现 WSGI/ASGI 协议,它们不在同一个层面。

用餐厅类比

角色对应做什么
大堂接待员NGINX(反向代理)迎客、引导、简单事务
厨房内部传菜规则WSGI / ASGI厨师和传菜员之间的协作规范
厨师(做菜的人)Flask / FastAPI真正的业务逻辑处理
厨房经理Gunicorn / Uvicorn分配工作、管理人手

NGINX 做的事情(HTTP 层面)

WSGI/ASGI 服务器做的事情(应用层面)

注意:NGINX 和 Gunicorn 之间通过普通 HTTP 协议通信(或 Unix Socket),不是 WSGI 协议。WSGI 协议只存在于 Gunicorn/uWSGI 和你的 Python 应用之间。

典型生产架构

浏览器 → NGINX (80/443) → Uvicorn (:8000) → FastAPI app
                              或
         NGINX → Gunicorn (WSGI workers) → Django app
                              或
         NGINX → Gunicorn (Uvicorn workers) → FastAPI app

实战 Gunicorn 跑 FastAPI 的正确姿势

FastAPI 是 ASGI 框架,Gunicorn 原生只懂 WSGI。直接 gunicorn main:app 会把 FastAPI 的 async 函数当同步函数调用,协程永远不会被 await,直接报错或返回错误结果。

正确做法:让 Gunicorn 用 Uvicorn worker 类来启动

gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker

这样 Gunicorn 只负责进程管理(master 进程 + 4 个 worker 子进程),每个 worker 内部实际是 Uvicorn 在跑,走 ASGI 协议。

两全其美:Gunicorn 的稳定进程管理 + Uvicorn 的异步能力。这就是架构图中虚线标注的"生产环境常见方案"