WSGI vs ASGI:Python Web服务器网关接口完全指南

WSGI ASGI 是什么?
WSGI(Web Server Gateway Interface)ASGI(Asynchronous Server Gateway Interface)是定义 Web 服务器如何与 Python Web 应用程序和框架通信的规范。
可以把它们想象成"合同""协议",确保 Web 服务器和 Python 应用能无缝协作。
WSGI(Web 服务器网关接口)
概述
创建时间:2003 年(PEP 333,后在 PEP 3333 更新)
目的:标准化 Web 服务器与 Python Web 应用之间的接口
模型:同步,阻塞 I/O
状态:成熟,广泛采用的标准
WSGI 如何工作
WSGI 定义了一个简单的双边接口:
服务器端:实现 WSGI Web 服务器
应用端:符合 WSGI Python 应用
WSGI 应用结构
WSGI 应用本质上是一个可调用对象(函数或类),它:
接受两个参数:environ start_response
返回一个字节字符串的可迭代对象
  1. def simple_wsgi_app(environ, start_response):
  2. """
  3. environ: 包含类 CGI 环境变量的字典
  4. start_response: 初始化 HTTP 响应的可调用对象
  5. """
  6. status = '200 OK'
  7. headers = [('Content-Type', 'text/plain')]
  8. start_response(status, headers)
  9. return [b'Hello, WSGI World!']

  10. # 基于类的 WSGI 应用
  11. class WSGIApp:
  12. def __call__(self, environ, start_response):
  13. status = '200 OK'
  14. headers = [('Content-Type', 'text/html')]
  15. start_response(status, headers)
  16. path = environ.get('PATH_INFO', '/')
  17. method = environ.get('REQUEST_METHOD', 'GET')
  18. response = f"""
  19. WSGI 应用

  20. 路径: {path}

  21. 方法: {method}

  22. """.encode('utf-8')
  23. return [response]

  24. app = WSGIApp()
python
WSGI 服务器
常见的 WSGI 服务器包括:
Gunicorn - Unix 系统的 Python WSGI HTTP 服务器
uWSGI - 全功能应用服务器
mod_wsgi - Apache 模块
Waitress - 生产级纯 Python WSGI 服务器
Werkzeug - 开发服务器(Flask 使用)
WSGI 框架
Django - 全功能 Web 框架
Flask - 轻量级微框架
Bottle - 极简框架
Pyramid - 灵活框架
使用 Flask WSGI 示例
  1. from flask import Flask

  2. app = Flask(__name__)

  3. @app.route('/')
  4. def hello():
  5. return 'Hello, WSGI with Flask!'

  6. @app.route('/user/')
  7. def user(name):
  8. return f'Hello, {name}!'

  9. # 这是一个 WSGI 应用
  10. # Flask 自动创建 WSGI 接口

  11. if __name__ == '__main__':
  12. # 开发服务器
  13. app.run(debug=True)
  14. # 生产环境使用 WSGI 服务器:
  15. # gunicorn app:app
python
ASGI(异步服务器网关接口)
概述
创建时间:2016
目的:扩展 WSGI 以支持异步 Python 和处理 WebSocket、HTTP/2
模型:异步,非阻塞 I/O
状态:现代异步 Python Web 应用的标准
为什么需要 ASGI?
WSGI 的局限:
仅同步 - 阻塞 I/O 操作
HTTP - 不能处理 WebSocket、HTTP/2 服务器推送
请求-响应循环 - 不支持长连接
线程开销 - 每个请求通常需要一个线程
ASGI 的解决方案:
异步 - 使用 async/await 的非阻塞 I/O
协议无关 - 支持 HTTP、WebSocket、HTTP/2
长连接 - 支持持久连接
更好的性能 - 单线程事件循环
ASGI 应用结构
ASGI 应用是一个异步可调用对象,它:
接受三个参数:scopereceivesend
使用 async/await 语法
  1. async def simple_asgi_app(scope, receive, send):
  2. """
  3. scope: 包含连接信息的字典
  4. receive: 接收消息的异步可调用对象
  5. send: 发送消息的异步可调用对象
  6. """
  7. if scope['type'] == 'http':
  8. await send({
  9. 'type': 'http.response.start',
  10. 'status': 200,
  11. 'headers': [[b'content-type', b'text/plain']],
  12. })
  13. await send({
  14. 'type': 'http.response.body',
  15. 'body': b'Hello, ASGI World!',
  16. })

  17. # 基于类的 ASGI 应用
  18. class ASGIApp:
  19. async def __call__(self, scope, receive, send):
  20. if scope['type'] == 'http':
  21. await self.handle_http(scope, receive, send)
  22. elif scope['type'] == 'websocket':
  23. await self.handle_websocket(scope, receive, send)
  24. async def handle_http(self, scope, receive, send):
  25. path = scope.get('path', '/')
  26. method = scope.get('method', 'GET')
  27. response_body = f"""
  28. ASGI 应用

  29. 路径: {path}

  30. 方法: {method}

  31. """.encode('utf-8')
  32. await send({
  33. 'type': 'http.response.start',
  34. 'status': 200,
  35. 'headers': [[b'content-type', b'text/html']],
  36. })
  37. await send({
  38. 'type': 'http.response.body',
  39. 'body': response_body,
  40. })
  41. async def handle_websocket(self, scope, receive, send):
  42. await send({'type': 'websocket.accept'})
  43. while True:
  44. message = await receive()
  45. if message['type'] == 'websocket.receive':
  46. await send({
  47. 'type': 'websocket.send',
  48. 'text': f"Echo: {message.get('text', '')}"
  49. })
  50. elif message['type'] == 'websocket.disconnect':
  51. break

  52. app = ASGIApp()
python
ASGI 服务器
常见的 ASGI 服务器包括:
Uvicorn - 闪电般快速的 ASGI 服务器
Hypercorn - 支持 HTTP/2 HTTP/3
Daphne - HTTP、HTTP/2 WebSocket 协议服务器
Gunicorn - 配合 uvicorn worker
ASGI 框架
FastAPI - 现代、高性能 API 框架
Starlette - 轻量级 ASGI 框架
Django - Django 3.0 开始支持 ASGI
Quart - Flask 的异步版本
Sanic - 异步 Web 框架
使用 FastAPI ASGI 示例
  1. from fastapi import FastAPI, WebSocket
  2. from fastapi.responses import HTMLResponse
  3. import asyncio
  4. import aiofiles

  5. app = FastAPI()

  6. @app.get("/")
  7. async def read_root():
  8. return {"Hello": "ASGI World"}

  9. @app.get("/async-file")
  10. async def read_file():
  11. # 非阻塞文件 I/O
  12. async with aiofiles.open('data.txt', mode='r') as f:
  13. content = await f.read()
  14. return {"content": content}

  15. @app.get("/slow-endpoint")
  16. async def slow_endpoint():
  17. # 非阻塞睡眠 - 其他请求可以继续处理
  18. await asyncio.sleep(5)
  19. return {"message": "这花了5秒但没有阻塞其他请求"}

  20. @app.websocket("/ws")
  21. async def websocket_endpoint(websocket: WebSocket):
  22. await websocket.accept()
  23. while True:
  24. data = await websocket.receive_text()
  25. await websocket.send_text(f"收到消息: {data}")

  26. # 运行:uvicorn main:app --reload
python
关键差异对比
方面
WSGI
ASGI
执行模型
同步,阻塞
异步,非阻塞
并发
线程/多进程
单线程事件循环
协议
HTTP
HTTP、WebSocket、HTTP/2
连接类型
仅请求-响应
支持长连接
I/O 操作
阻塞
非阻塞
内存使用
较高(每请求一个线程)
较低(共享事件循环)
性能
CPU 密集型任务好
I/O 密集型任务好
复杂度
较简单
较复杂
成熟度
非常成熟(20+年)
较新(8+年)
性能对比
WSGI 性能特征
  1. # WSGI - 每个请求都会阻塞直到完成
  2. import time
  3. import requests

  4. def wsgi_blocking_operation():
  5. # 这会阻塞整个线程
  6. time.sleep(1) # 模拟数据库查询
  7. return "数据库数据"

  8. @app.route('/data')
  9. def get_data():
  10. result = wsgi_blocking_operation()
  11. return result

  12. # 10个并发请求:
  13. # - WSGI 需要10个线程
  14. # - 总时间:~1秒(有足够线程时)
  15. # - 内存使用:高(线程开销)
python
ASGI 性能特征
  1. # ASGI - 并发请求互不阻塞
  2. import asyncio
  3. import aiohttp

  4. async def asgi_async_operation():
  5. # 不会阻塞事件循环
  6. await asyncio.sleep(1) # 模拟异步数据库查询
  7. return "数据库数据"

  8. @app.get('/data')
  9. async def get_data():
  10. result = await asgi_async_operation()
  11. return result

  12. # 10个并发请求:
  13. # - ASGI 使用单个事件循环
  14. # - 总时间:~1秒(所有请求并发处理)
  15. # - 内存使用:低(无线程开销)
python
何时使用哪个
使用 WSGI 的场景:
构建传统 Web 应用
使用成熟框架(Django、Flask)
CPU 密集型操作
简单的请求-响应模式
团队熟悉同步编程
现有基础设施基于 WSGI
使用 ASGI 的场景:
构建现代 API 或微服务
需要 WebSocket 支持
I/O 操作(数据库、文件系统、网络调用)
实时应用
需要并发请求的最大性能
从头开始构建新应用
迁移考虑
WSGI ASGI 迁移
  1. # WSGI Flask 应用
  2. from flask import Flask
  3. app = Flask(__name__)

  4. @app.route('/')
  5. def hello():
  6. return 'Hello World'

  7. # 转换为使用 QuartASGI
  8. from quart import Quart
  9. app = Quart(__name__)

  10. @app.route('/')
  11. async def hello():
  12. return 'Hello World'

  13. # 或使用 ASGI 适配器
  14. from asgiref.wsgi import WsgiToAsgi
  15. from flask import Flask

  16. flask_app = Flask(__name__)
  17. app = WsgiToAsgi(flask_app)
python
同时运行两者
  1. # 可以使用适配器在 ASGI 服务器上运行 WSGI 应用
  2. from fastapi import FastAPI
  3. from fastapi.middleware.wsgi import WSGIMiddleware
  4. from flask import Flask

  5. # WSGI Flask 应用
  6. flask_app = Flask(__name__)

  7. @flask_app.route('/legacy')
  8. def legacy_endpoint():
  9. return '这是一个传统的 WSGI 端点'

  10. # ASGI FastAPI 应用
  11. fastapi_app = FastAPI()

  12. @fastapi_app.get('/modern')
  13. async def modern_endpoint():
  14. return {'message': '这是一个现代的 ASGI 端点'}

  15. # 在 ASGI 应用中挂载 WSGI 应用
  16. fastapi_app.mount('/wsgi', WSGIMiddleware(flask_app))
python
结论
WSGI 仍然非常适合传统 Web 应用,特别是在使用成熟框架和团队熟悉同步编程的情况下。
ASGI 是高性能、现代 Web 应用的未来,特别是需要处理大量并发连接、实时功能或密集 I/O 操作的场景。
许多组织正在逐步从 WSGI 迁移到 ASGI,或在过渡期使用混合方法让两者共存。