WSGI 与 ASGI
问题
WSGI 和 ASGI 是什么?它们之间有什么区别?
答案
WSGI(Web Server Gateway Interface)和 ASGI(Asynchronous Server Gateway Interface)是 Python Web 应用与服务器之间的标准接口协议。
WSGI(PEP 3333)
同步协议,一个请求占用一个线程:
# 最简 WSGI 应用
def application(environ: dict, start_response):
"""
environ: 请求环境变量(路径、方法、请求头等)
start_response: 回调函数,设置状态码和响应头
"""
status = "200 OK"
headers = [("Content-Type", "text/plain")]
start_response(status, headers)
return [b"Hello, World!"]
WSGI 服务器:Gunicorn、uWSGI、Waitress
# Gunicorn 部署 Flask/Django
gunicorn app:application -w 4 -b 0.0.0.0:8000
ASGI
异步协议,原生支持 WebSocket 和 HTTP/2:
# 最简 ASGI 应用
async def application(scope: dict, receive, send):
"""
scope: 连接信息(类型、路径、请求头等)
receive: 接收消息的协程
send: 发送消息的协程
"""
if scope["type"] == "http":
await send({
"type": "http.response.start",
"status": 200,
"headers": [(b"content-type", b"text/plain")],
})
await send({
"type": "http.response.body",
"body": b"Hello, Async World!",
})
ASGI 服务器:Uvicorn、Hypercorn、Daphne
# Uvicorn 部署 FastAPI
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4
核心区别
| 特性 | WSGI | ASGI |
|---|---|---|
| 并发模型 | 同步(1 请求 = 1 线程) | 异步(事件循环) |
| WebSocket | 不支持 | 原生支持 |
| HTTP/2 | 不支持 | 支持 |
| 框架 | Django, Flask | FastAPI, Starlette, Django 3.0+ |
| 服务器 | Gunicorn, uWSGI | Uvicorn, Hypercorn |
| 性能 | I/O 密集型较差 | I/O 密集型优秀 |
常见面试问题
Q1: Django 能用 ASGI 吗?
答案:
Django 3.0+ 支持 ASGI,但 ORM 仍然是同步的。需要用 sync_to_async 包装 ORM 操作:
from asgiref.sync import sync_to_async
@sync_to_async
def get_user(user_id):
return User.objects.get(id=user_id)
# 在 async view 中使用
async def user_view(request, user_id):
user = await get_user(user_id)
return JsonResponse({"name": user.name})
Q2: Gunicorn 和 Uvicorn 怎么配合?
答案:
生产环境常用 Gunicorn + Uvicorn Worker 的组合:
# Gunicorn 管理进程,Uvicorn 处理异步请求
gunicorn app:app -k uvicorn.workers.UvicornWorker -w 4
Gunicorn 负责进程管理(worker 重启、信号处理),Uvicorn Worker 负责异步 I/O。
Q3: WSGI 中间件和 ASGI 中间件有什么区别?
答案:
WSGI 中间件是同步函数包装器,ASGI 中间件是异步的:
# WSGI 中间件
class WSGIMiddleware:
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
# 前处理
return self.app(environ, start_response)
# ASGI 中间件
class ASGIMiddleware:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
# 前处理
await self.app(scope, receive, send)