概述
Python Web服务器网关接口有三种标准,分别针对异步、实时同步和传统同步Web应用场景设计,即ASGI、RSGI、WSGI。
| 标准 | 全称 | 中文含义 | 发布时间 |
|---|---|---|---|
| WSGI | Web Server Gateway Interface | Web服务器网关接口 | 2003年 |
| ASGI | Asynchronous Server Gateway Interface | 异步服务器网关接口 | 2016年 |
| RSGI | Real-time Server Gateway Interface | 实时服务器网关接口 | 2023年 |
WSGI
示例代码:
py
def application(environ, start_response):
status = '200 OK'
headers = [('Content-Type', 'text/plain')]
start_response(status, headers)
return [b"Hello World"]
特点:
- 同步阻塞:一个请求处理完才能处理下一个
- 单线程模型:不适合高并发
- 简单稳定:成熟稳定,生态完善
Web框架举例:Django、Flask、Pyramid、Bottle
优势
- 成熟稳定:近20年发展,bug极少
- 生态丰富:几乎所有Python Web框架支持
- 简单易学:同步编程模型直观
- 部署简单:Gunicorn、uWSGI等成熟方案
劣势
- 性能瓶颈:同步阻塞,高并发需多进程
- 协议落后:不支持WebSocket、HTTP/2
- 资源消耗:每个请求一个进程/线程
- 实时性差:不适合实时应用
工作原理
核心思想是将Web应用程序与Web服务器解耦,规定应用程序需要实现的接口,以便能够与任何兼容WSGI的Web服务器通信。使得开发者可专注于应用程序的逻辑,而无需关心与特定Web服务器的交互。
两个主要组件:
- 应用程序(Application):WSGI应用程序是一个可调用对象,通常是一个函数或一个类的实例。接受两个参数:
environ和start_response,并返回一个迭代器,用于生成HTTP响应。 - 服务器网关(Server Gateway):服务器网关是一个中间件组件,负责处理HTTP请求并将请求传递给WSGI应用程序。服务器网关还负责调用应用程序生成的响应,并将响应返回给客户端。
中间件
WSGI中间件一种用于在WSGI应用程序和Web服务器之间执行预/后处理操作的机制,可用于添加额外的功能,如请求/响应处理、身份验证、缓存等,是构建复杂Web应用程序的重要组成部分。
作用包括:
- 请求处理:可在请求到达应用程序之前执行一些处理逻辑,如身份验证、请求重定向等。
- 响应处理:可在应用程序生成响应后对响应进行处理,如添加HTTP头、压缩响应内容等。
- 异常处理:可捕获应用程序抛出的异常,并根据需要执行特定的操作,如记录错误日志、返回自定义错误页面等。
uWSGI
一个应用服务器,实现WSGI协议并提供高性能的Web应用程序托管环境。支持多种协议,包括HTTP、FastCGI、SCGI等,使得Python应用程序可与不同类型的Web服务器通信。
相比开发环境中的简易服务器(如Django的runserver或Flask的Werkzeug),在生产环境中具备更强的并发处理能力和更多高级特性,如负载均衡、缓存。
实战
安装:pip install uwsgi
指定脚本启动:uwsgi --http :9090 --wsgi-file myapp.py --master --processes 4 --threads 2,生成4个进程,每个进程有2个线程。适合开发阶段。
生产环境,一般需要创建uWSGI配置文件myapp_uwsgi.ini,指定WSGI应用程序:
ini
[uwsgi]
; 虚拟环境绝对路径,Docker部署时不需要
home=/opt/python_venv/test_project
; 项目的绝对路径
chdir = /opt/project/test_project
; 项目名
project=flask_demo
; 启动路由:指定启动协议,当和nginx结合进行反向代理,就用unix-socket协议,无法直接访问,只能通过nginx进行反代
socket=0.0.0.0:8000
; 项目启动入口文件,默认入口函数是application
wsgi-file=main.py
; 入口文件中的函数,如flask文件中的app
callable=app
; 启用process manager,管理worker进程,worker进程都是master进程的子进程
master=True
; 指定开启的工作进程数量,一般指定为cpu的核数即可(填cpu的4倍数量)
processes=1
; 设置每个工作进程的线程数
threads=2
; 设置用于uwsgi包解析的内部缓存区大小为64k,默认是4k
buffer-size = 32768
; 使进程在后台运行,并将日志打到指定的日志文件或者udp服务器
daemonize = /var/log/test_project/uwsgi.log
; 设置最大日志文件大小
; log-maxsize = 5000000
; 指定pid文件的位置,记录主进程的pid号
pidfile=uwsgi.pid
; 当服务器退出的时候自动删除unix socket文件和pid文件
vacuum = true
; 格式化日志打印
logformat-strftime=true
log-date=%%Y-%%m-%%d %%H:%%M:%%S
log-format=[%(ftime)] pid: %(pid) %(addr) => host: %(host)%(uri)(%(method)) in %(secs)s %(status) total-size: %(size) bytes
备注:CSDN编辑器太垃圾,不支持ini脚本语言,;表示注释。
启动uWSGI服务器,并托管Python应用:uwsgi --ini myapp_uwsgi.ini。
其他命令:
bash
# 重启uWSGI服务器
$ uwsgi --reload uwsgi.pid
# 查看所有uWSGI进程
$ ps aux | grep uwsgi
# 停止uWSGI服务器
$ uwsgi --stop uwsgi.pid # 启动时会生成uwsgi.pid文件
uwsgi
一个通信协议,定义应用服务器和Web服务器之间的通信方式。uWSGI是uwsgi的一种实现。
ASGI
示例代码:
py
async def application(scope, receive, send):
await send({
'type': 'http.response.start',
'status': 200,
'headers': [[b'content-type', b'text/plain']]
'body': b"Hello World"
})
特点:
- 异步非阻塞:一个请求等待时处理其他请求
- 支持WebSocket:原生支持实时通信
- 高性能:适合高并发场景
Web框架举例:FastAPI、Starlette、Django Channels、BlackSheep
优势
- 高性能:单进程处理数千并发
- 现代协议:原生支持WebSocket、HTTP/2
- 资源高效:低内存占用,高CPU利用率
- 实时性强:适合实时通信应用
劣势
- 学习曲线:需要理解异步编程概念
- 调试困难:异步代码调试更复杂
- 生态迁移:部分WSGI库需重写
- 阻塞风险:同步代码可能阻塞事件循环
RSGI
示例代码:
py
def application(scope, receive, send):
# 同步接口,但支持流式响应
send({
'type': 'http.response.start',
'status': 200,
'headers': [[b'content-type', b'text/plain']]
})
# 支持分块传输
send({
'type': 'http.response.body',
'body': b"Hello ",
'more_body': True
})
send({
'type': 'http.response.body',
'body': b"World"
})
特点:
- 同步但支持流式:保持同步编程模型
- 实时响应:支持服务器推送
- 兼容WSGI:迁移成本低
诞生于2023年
- 背景:部分开发者不适应异步编程模型
- 问题:ASGI学习曲线陡峭,WSGI功能有限
- 解决方案:RSGI保持同步模型但支持现代特性
- 定位:WSGI和ASGI之间的折中方案
优势
- 平衡折中:同步编程+现代特性
- 迁移简单:WSGI应用易迁移
- 实时支持:支持流式响应
- 学习友好:无需掌握异步编程
劣势
- 新生标准:生态不成熟
- 性能折中:不如ASGI高性能
- 定位模糊:可能被ASGI和WSGI挤压
- 社区认可:需要时间验证
对比
核心差异矩阵
| 维度 | WSGI | ASGI | RSGI |
|---|---|---|---|
| 编程模型 | 同步阻塞 | 异步非阻塞 | 同步流式 |
| 并发能力 | 低(依赖多进程) | 高(单线程异步) | 中(多线程/进程) |
| 实时支持 | 不支持 | 原生支持 | 支持流式 |
| 学习曲线 | 简单 | 较陡(需理解async/await) | 中等 |
| 生态成熟度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ |
| 性能表现 | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| 内存占用 | 高(多进程) | 低(单进程) | 中 |
| 适用场景 | 传统Web应用 | 高并发实时应用 | 实时同步应用 |
协议支持对比
| 协议 | WSGI | ASGI | RSGI |
|---|---|---|---|
| HTTP/1.1 | ✅ | ✅ | ✅ |
| HTTP/2 | ❌ | ✅ | ✅ |
| WebSocket | ❌ | ✅ | ✅(受限) |
| Server-SentEvents | ❌ | ✅ | ✅ |
| 长轮询 | 有限 | ✅ | ✅ |
| 分块传输 | ❌ | ✅ | ✅ |
性能基准测试(估算)
| 场景 | WSGI | ASGI | RSGI |
|---|---|---|---|
| 1000并发请求 | 500-800ms | 50-100ms | 200-300ms |
| WebSocket连接 | 不支持 | 10000+连接 | 5000+连接 |
| 内存占用(100并发) | 500MB+ | 100MB- | 300MB |
| CPU利用率 | 高(上下文切换) | 高(事件循环) | 中 |
Gunicorn
官网,Green Unicorn缩写,开源(GitHub,10.5K Star,1.8K Fork)高性能的 Python WSGI UNIX HTTP服务器,移植自Ruby的独角兽(Unicorn)项目。
特性:
- 原生支持WSGI、Django和Paster
- 自动工作进程管理
- 简单的Python配置
- 多Worker配置
- 多种可扩展性服务器挂钩
- 兼容Python 3.5+
Gunicorn从5个地方依次读取配置:
- 环境变量
- 框架配置
gunicorn.conf.py配置文件- 环境变量中的GUNICORN_CMD_ARGS
- 命令行
常见配置项:
--config:配置文件--reload:代码更改时重新启动--access-logfile:要写入的访问日志文件--error-logfile:要写入的错误日志文件--log-level:错误输出级别--certfile:SSL证书文件--bind:绑定socket--workers:处理请求的工作进程数--threads:用于处理请求的工作线程数
服务器钩子
on_starting:在主进程初始化之前调用on_reload:重新加载期间调用when_ready:在服务器启动后立即调用pre_fork:在fork之前调用post_fork:在fork之后调用post_worker_init:在work初始化之后调用worker_int:在worker退出SIGINT或SIGQUIT后立即调用worker_abort:在worker收到SIGABRT信号时调用pre_exec:新的主进程之前调用pre_request:处理请求之前调用post_request:处理请求后调用child_exit:在主进程中退出工作程序后立即调用worker_exit:worker退出后调用nworkers_changed:在num_workers更改后立即调用on_exit:在退出Gunicorn之前调用
实战
安装
- 基于
pip:pip install gunicorn - 基于源码:
pip install git+https://github.com/benoitc/gunicorn.git
若需要使用异步workers,还需要安装:
bash
pip install greenlet # Required for both
pip install eventlet # For eventlet workers
pip install gunicorn[eventlet] # Or, using extra
pip install gevent # For gevent workers
pip install gunicorn[gevent] # Or, using extra
命令行示例:
bash
gunicorn --workers=2 test:app
# 工厂模式,指定方法
gunicorn --workers=2 'test:create_app()'
Uvicorn
官网,开源(GitHub,10.6K Star,932 Fork)基于asyncio、高性能ASGI服务器,用于构建异步Web服务,支持HTTP和WebSocket协议。
应用场景
- 异步API服务:处理大量并发请求,提高系统的性能和吞吐量
- Websocket服务:可用于构建实时通信的Web应用程序
实战
提供多种安装方式:
- pip:
pip install uvicorn - uv:
uv install uvicorn
命令行:
bash
uvicorn main:app --reload
uvicorn main:app --ssl-keyfile key.pem --ssl-certfile cert.pem
解读:
- 支持通过SSL加密来提供安全的通信。可使用
--ssl-keyfile和--ssl-certfile参数来指定SSL密钥文件和证书文件
常用配置选项:
--host:指定主机地址,默认为127.0.0.1--port:指定端口号,默认为8000--workers:指定工作进程数量,默认为CPU核心数的1倍--log-level:指定日志级别,默认为info--reload:在代码修改时自动重新加载应用程序
支持处理WebSocket连接,用于实时通信应用程序
py
# websocket_app.py
from fastapi import FastAPI, WebSocket
app = FastAPI()
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Message text was: {data}")
支持使用中间件来修改请求和响应,以及执行其他自定义操作。可通过--middleware参数来指定中间件。
py
# middleware.py
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
from uvicorn.middleware.debug import DebugMiddleware
from fastapi import FastAPI
app = FastAPI()
app.add_middleware(ProxyHeadersMiddleware, trusted_hosts=["10.0.0.1"])
app.add_middleware(DebugMiddleware)
@app.get("/")
async def read_root():
return {"message": "Hello, World!"}
支持在异步Web服务中执行异步任务,不会阻塞主事件循环:
py
# async_task.py
from fastapi import FastAPI
import asyncio
app = FastAPI()
async def background_task():
while True:
print("Background task is running...")
await asyncio.sleep(5)
@app.on_event("startup")
async def startup_event():
asyncio.create_task(background_task())
@app.get("/")
async def read_root():
return {"message": "Hello, World!"}
可通过自定义异常处理器来处理异常情况,如未找到页面、服务器错误等。
py
# error_handling.py
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id == 42:
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id}
py