Uvicorn实操教程
📖 一. Uvicorn概要
Uvicorn是一个基于uvloop和httptools构建的高性能 ASGI 服务器 (Asynchronous Server Gateway Interface)。
核心特点:
-
支持 ASGI 1/2/3 规范,兼容所有异步 Web 框架;
-
高性能:uvloop 替代标准库
asyncio的事件循环,性能接近 Node.js 或 Go; -
轻量易用:单文件启动,配置灵活;
-
支持 HTTP/1.1、WebSocket、HTTP/2(需额外依赖);
-
可与 Gunicorn 配合,实现多进程+多线程部署。
⚙️ 二. 环境准备
🐍 2.1 安装 Python
确保 Python 版本 ≥ 3.8(异步语法和 ASGI 规范要求)。
📦 2.2 安装 Uvicorn
# 基础安装(仅核心功能)
pip install uvicorn
# 完整安装(支持 HTTP/2、WebSocket 等)
pip install uvicorn[standard]
# 验证安装
uvicorn --version
# 查看命令帮助
uvicorn --help
🎛️ 三. 核心参数
Uvicorn 支持丰富的命令行参数,常用参数如下:
🔧 3.1 基础参数
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
app | str/object | 应用路径或实例 | 必填 |
host | str | 绑定主机地址 | "127.0.0.1" |
port | int | 监听端口 | 8000 |
🛠️ 3.2 开发参数
| 参数 | 类型 | 说明 | 注意事项 |
|---|---|---|---|
reload | bool | 代码变更自动重启 | 与 workers 互斥 |
reload_dirs | list | 监控目录列表 | 配合 reload 使用 |
reload_includes | list | 监控文件模式 | 如 ["*.py", "*.yaml"] |
reload_excludes | list | 排除文件模式 | 如 ["*.pyc"] |
🚀 3.3 生产参数
| 参数 | 类型 | 说明 | 推荐值 |
|---|---|---|---|
workers | int | 工作进程数 | CPU 核心数 * 2 + 1 |
loop | str | 事件循环 | "uvloop" |
http | str | HTTP 实现 | "httptools" |
proxy_headers | bool | 信任代理头 | 反向代理场景设为 True |
forwarded_allow_ips | str | 允许的代理 IP | 具体 IP 或 "*" |
📊 3.4 日志参数
| 参数 | 类型 | 说明 | 可选值 |
|---|---|---|---|
log_level | str | 日志级别 | critical/error/warning/info/debug/trace |
access_log | bool | 访问日志 | True/False |
use_colors | bool | 彩色日志 | True/False |
log_config | dict/str | 自定义日志配置 | 日志配置文件路径或字典 |
🔌 3.5 连接参数
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
timeout_keep_alive | int | Keep-Alive 超时(秒) | 5 |
limit_concurrency | int | 最大并发连接数 | None(无限制) |
limit_max_requests | int | 进程重启前最大请求数 | None(无限制) |
💡 3.6 应用示例
3.6.1 开发参数配置
uvicorn.run(
"main:app",
host="127.0.0.1",
port=8000,
reload=True, # 热重载
log_level="debug", # 详细日志
access_log=True,
use_colors=True
)
3.6.2 生产参数配置
import multiprocessing
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8000,
workers=multiprocessing.cpu_count() * 2 + 1, # 根据 CPU 核心数
loop="uvloop", # 高性能事件循环
http="httptools", # 高性能 HTTP 解析
log_level="warning", # 生产环境减少日志
access_log=False, # 关闭访问日志(可选)
proxy_headers=True, # 信任代理
forwarded_allow_ips="*",
timeout_keep_alive=30,
limit_concurrency=1000 # 限制并发
)
3.6.3 命令行参数
# 开发模式:自动重载 + 调试日志 + 自定义端口
uvicorn main:app --host 0.0.0.0 --port 8000 --reload --log-level debug
# 生产模式:多进程(4个worker)
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
# HTTPS 模式(需提前生成证书)
uvicorn main:app --ssl-keyfile ./key.pem --ssl-certfile ./cert.pem
🎯 四. ASGI应用示例
📝 4.1 编写ASGI应用
ASGI 协议要求 HTTP 响应必须分两步发送:发送状态码和响应头 -> 发送响应体。
# File: main.py
async def app(scope, receive, send):
if scope["type"] == "http":
headers = headers or [(b"content-type", b"text/plain")]
await send({"type": "http.response.start", "status": 200, "headers": headers})
await send({"type": "http.response.body", "body": b"Hello, World!"})
▶️ 4.2 启动Uvicorn服务
# uvicorn <模块名:应用对象> [paraments]
uvicorn main:app
# 自定义参数启动
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
打开浏览器访问 http://127.0.0.1:8000 测试。
🎬 五. FastAPI实践
Uvicorn 是 FastAPI 的官方推荐服务器,两者搭配是异步 Web 开发的黄金组合。
📦 5.1 安装FastAPI
pip install fastapi
💻 5.2 命令行启动
代码示例:main.py
from fastapi import FastAPI
app = FastAPI(title="Awesome", description="Welcome FastAPI", version="1.0.0")
@app.get("/")
async def home():
return {"msg": "Hello World"}
运行服务
# 基础启动
uvicorn main:app
# 指定主机和端口
uvicorn main:app --host 0.0.0.0 --port 8000
# 开发模式(热重载)
uvicorn main:app --reload
# 生产环境(多进程启动)
uvicorn main:app --workers 4
🔨 5.3 代码内启动
代码示例:main.py
import uvicorn
from fastapi import FastAPI
app = FastAPI(title="Awesome", description="Welcome FastAPI", version="1.0.0")
@app.get("/")
async def home():
return {"msg": "Hello World"}
if __name__ == "__main__":
# 最简单的方式
# uvicorn.run(app)
# 指定主机和端口
# uvicorn.run(app, host="0.0.0.0", port=8000)
# 工厂方法+完整参数
uvicorn.run(
"main:app", # 应用路径(字符串格式,支持 reload 和 workers)
host="0.0.0.0", # 监听所有网络接口
port=8000, # 端口号
reload=True, # 热重载(开发环境)
workers=4, # 工作进程数(生产环境,与 reload 互斥)
loop="uvloop", # 事件循环实现(需安装 uvloop)
http="httptools", # HTTP 协议实现(需安装 httptools)
log_level="info", # 日志级别: critical/error/warning/info/debug/trace
access_log=True, # 启用访问日志
use_colors=True, # 日志彩色输出
proxy_headers=True, # 信任代理头(部署在反向代理后)
forwarded_allow_ips="*", # 允许的代理 IP(* 表示信任所有)
root_path="./", # 根路径(用于代理后的路径前缀)
timeout_keep_alive=5 # Keep-Alive 超时时间(秒)
)
运行服务
python main.py
🏗️ 5.4 服务实例启动
代码示例:main.py
import uvicorn
from fastapi import FastAPI
app = FastAPI(title="Awesome", description="Welcome FastAPI", version="1.0.0")
@app.get("/")
async def home():
return {"msg": "Hello World"}
if __name__ == "__main__":
config = uvicorn.Config("main:app", host="0.0.0.0", port=8000) # 支持所有可用参数
server = uvicorn.Server(config)
server.run()
运行服务
python main.py
♻️ 5.5 生命周期控制
代码示例:main.py
import asyncio
import signal
import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def home(): return {"msg": "Hello World"}
class CustomServer(uvicorn.Server):
"""自定义服务器,支持优雅关闭"""
def install_signal_handlers(self):
pass # 禁用默认信号处理
async def main():
config = uvicorn.Config("main:app", host="0.0.0.0", port=8000)
server = CustomServer(config)
# 自定义信号处理
def handle_exit(sig, frame):
print("收到退出信号,优雅关闭...")
asyncio.create_task(server.shutdown())
signal.signal(signal.SIGINT, handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
# 启动服务器
await server.serve()
if __name__ == "__main__":
asyncio.run(main())
运行服务
python main.py
⚖️ 六. 同步与异步
📝 6.1 示例代码
# main.py
from fastapi import FastAPI
import uvicorn
import time
import asyncio
import threading
app = FastAPI()
# 全局计数器
counter = 0
counter_lock = threading.Lock()
# ---------------------- 1. 线程池模式(普通同步函数) ----------------------
@app.get("/pool")
def pool_handler():
global counter
# 这是普通同步函数,FastAPI会自动把它放到「线程池」里执行
# 多个请求会被不同线程同时处理,sleep只阻塞当前线程,不影响其他请求
time.sleep(1)
with counter_lock:
counter += 1
print(f"当前计数: {counter},线程ID: {threading.get_ident()}")
# --------------------- 2. 阻塞模式(强制阻塞事件循环) ----------------------
@app.get("/blocking")
async def blocking_handler():
global counter
# 异步函数内直接用同步sleep,卡住“总调度器”事件循环)
# 其他请求必须等这个sleep结束才能处理
time.sleep(1)
with counter_lock:
counter += 1
print(f"当前计数: {counter},线程ID: {threading.get_ident()}")
# ---------------------- 3. 线程池隔离模式(推荐) --------------------------
@app.get("/async-thread")
async def async_thread_handler():
global counter
# 在异步函数中调用同步操作,手动放入线程池隔离
# 既能使用同步库,又不阻塞事件循环(生产环境推荐)
await asyncio.to_thread(time.sleep, 1)
with counter_lock:
counter += 1
print(f"当前计数: {counter},线程ID: {threading.get_ident()}")
# ---------------------- 4. 纯异步模式(性能最优) -------------------------
@app.get("/async")
async def async_handler():
global counter
# 纯异步IO操作,不阻塞事件循环
# 协程在等待时释放控制权,其他请求可并发执行
await asyncio.sleep(1)
with counter_lock:
counter += 1
print(f"当前计数: {counter},线程ID: {threading.get_ident()}")
# ----------------------------------------------------------------------
if __name__ == "__main__":
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
access_log=False, # 关闭访问日志
log_level="warning", # 只显示警告和错误
workers=1, # 👉 使用单个工作进程
loop="asyncio" # 👉 使用asyncio事件循环,强制用Python原生“总调度器”(避免环境差异导致结果不准)
)
启动服务 :
python main.py
🔍 6.2 测试工具
1. ab工具(首选,简单直接):
- Linux/Mac:终端直接输入
ab即可使用; - Windows:需安装Apache服务器(或改用wrk工具);
2. 备选工具(可视化):locust(有可视化界面)
pip install locust # 安装后可通过网页看并发效果
✅ 6.3 测试验证
测试用例: 用10个用户同时请求(-c 10)、总共发10次请求(-n 10)。
ab -n 10 -c 10 http://127.0.0.1:8000/pool
# 测试结果:
# 总耗时≈1秒(10个请求并行执行,1秒后一起完成),输出如下:
当前计数: 1,线程ID: 123145361977344
当前计数: 2,线程ID: 123145361977344
当前计数: 3,线程ID: 123145429135360
当前计数: 4,线程ID: 123145445924864
当前计数: 5,线程ID: 123145462714368
当前计数: 6,线程ID: 123145479503872
当前计数: 7,线程ID: 123145496293376
当前计数: 8,线程ID: 123145378766848
当前计数: 9,线程ID: 123145412345856
当前计数: 10,线程ID: 123145395556352
ab -n 10 -c 10 http://127.0.0.1:8000/blocking
# 测试结果:
# 总耗时≈10秒(10个请求排队,严格串行,1个处理完再处理下一个,每秒处理1个),输出如下:
当前计数: 11,线程ID: 140704526526976
当前计数: 12,线程ID: 140704526526976
当前计数: 13,线程ID: 140704526526976
当前计数: 14,线程ID: 140704526526976
当前计数: 15,线程ID: 140704526526976
当前计数: 16,线程ID: 140704526526976
当前计数: 17,线程ID: 140704526526976
当前计数: 18,线程ID: 140704526526976
当前计数: 19,线程ID: 140704526526976
当前计数: 20,线程ID: 140704526526976
ab -n 10 -c 10 http://127.0.0.1:8000/async-thread
# 测试结果:
# 总耗时≈1秒;计数快速从1涨到10(并行执行),输出如下:
当前计数: 21,线程ID: 140704526526976
当前计数: 22,线程ID: 140704526526976
当前计数: 23,线程ID: 140704526526976
当前计数: 24,线程ID: 140704526526976
当前计数: 25,线程ID: 140704526526976
当前计数: 26,线程ID: 140704526526976
当前计数: 27,线程ID: 140704526526976
当前计数: 28,线程ID: 140704526526976
当前计数: 29,线程ID: 140704526526976
当前计数: 30,线程ID: 140704526526976
ab -n 10 -c 10 http://127.0.0.1:8000/async
# 测试结果:
# 总耗时≈1秒;计数快速从1涨到10(协程并行执行),输出如下:
当前计数: 31,线程ID: 140704526526976
当前计数: 32,线程ID: 140704526526976
当前计数: 33,线程ID: 140704526526976
当前计数: 34,线程ID: 140704526526976
当前计数: 35,线程ID: 140704526526976
当前计数: 36,线程ID: 140704526526976
当前计数: 37,线程ID: 140704526526976
当前计数: 38,线程ID: 140704526526976
当前计数: 39,线程ID: 140704526526976
当前计数: 40,线程ID: 140704526526976
🎯 6.4 结果说明
| 接口路径 | 执行方式 | 是否阻塞事件循环 | 10并发耗时 | 适用场景 |
|---|---|---|---|---|
| /pool | 线程池并行 | 不阻塞 | ≈1秒 | 普通同步接口(FastAPI默认处理方式) |
| /blocking | 事件循环主线程串行 | 阻塞 | ≈10秒 | 演示极端阻塞场景(生产环境避免) |
| /async-thread | 线程池并行(手动指定) | 不阻塞 | ≈1秒 | 需使用同步库但要保证并发的场景 |
| /async | 协程并行 | 不阻塞 | ≈1秒 | 原生异步IO操作(数据库/网络请求) |
🚀 6.5 最佳实践
6.5.1 线程池模式vs异步模式
| 对比维度 | 纯线程池(同步) | 多Worker+原生Async |
|---|---|---|
| 并发性能 | 中等(线程切换开销高) | 极高(协程开销极低) |
| 资源利用率 | 低(内存/CPU浪费) | 高(最大化多核/单核) |
| 开发/维护成本 | 开发低/维护高 | 开发中/维护低 |
| 扩展性 | 弱(线程数受限) | 强(线性扩容) |
6.5.2 融合方案(最佳实践)
推荐: Async + 多 Worker(核心)+ 线程池(兜底)
# 生产环境推荐配置(Linux/Mac)
uvicorn main:app \
--host 0.0.0.0 \
--port 8000 \
--workers $(( $(nproc) * 2 )) # Worker数=CPU核心数×2(IO密集最优)
--loop uvloop \ # 高性能异步循环(比原生asyncio快30%+)
--threads 20 # 线程池大小(仅兜底同步操作,20~50足够)
--workers:IO 密集场景设为 CPU 核心数 ×2,充分利用多核;CPU 密集场景设为 CPU 核心数;--threads:线程池仅处理同步逻辑,无需过大(避免线程切换开销)。
🚢 七. 生产部署实践
🎯 7.1 方案选择
-
Gunicorn:强项是【进程管理】,适配同步 WSGI 应用,生产环境中作为【主服务器】管理 Worker 进程;
-
Uvicorn:强项是【异步协议】,适配 ASGI 应用,生产环境中作为【Worker 内核】被 Gunicorn 管理;
-
生产最佳实践:
Gunicorn(进程管理) + Uvicorn(异步处理)(异步应用),或Gunicorn 单独(同步应用); -
开发环境: 直接用 Uvicorn(带热重载),简单高效。
🔧 7.2 方案实施
7.2.1 安装依赖
pip install gunicorn
7.2.2 命令行参数启动
# Gunicorn 管理 Uvicorn 工作进程
gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
7.2.3 配置文件启动
创建 gunicorn_config.py:
# gunicorn_config.py
bind = "0.0.0.0:8000"
workers = 4 # 推荐值:CPU核心数 * 2 + 1
worker_class = "uvicorn.workers.UvicornWorker"
timeout = 60
keepalive = 5
log_level = "info"
accesslog = "./access.log" # 访问日志
errorlog = "./error.log" # 错误日志
启动服务:
gunicorn -c gunicorn_config.py main:app
🛡️ 7.3 进程守护
生产环境建议用 supervisor 或 systemd 守护进程,防止服务意外退出。
示例 systemd 配置(/etc/systemd/system/uvicorn-app.service):
[Unit]
Description=Uvicorn FastAPI Service
After=network.target
[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/app
ExecStart=/home/ubuntu/venv/bin/gunicorn -c gunicorn_config.py main:app
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
启动并设置开机自启
sudo systemctl daemon-reload
sudo systemctl start uvicorn-app
sudo systemctl enable uvicorn-app
🔥 八. 性能调优建议
⚙️ 8.1 工作进程数设置
import multiprocessing
# CPU 密集型应用
workers = multiprocessing.cpu_count()
# I/O 密集型应用(推荐)
workers = multiprocessing.cpu_count() * 2 + 1
🚀 8.2 使用高性能依赖
-
uvloop:基于libuv替代asyncio默认事件循环,大幅提升异步I/O性能;
-
httptools:C实现的HTTP解析器,替代h11,提速HTTP解析、降低CPU消耗。
pip install uvloop httptools
uvicorn.run(
"main:app",
loop="uvloop",
http="httptools"
)
🔌 8.3 调整连接参数
uvicorn.run(
"main:app",
timeout_keep_alive=30, # 增加 Keep-Alive 时间
limit_concurrency=1000, # 限制最大并发
limit_max_requests=10000 # 定期重启 worker(防止内存泄漏)
)
📊 8.4 日志优化
# 生产环境减少日志开销
uvicorn.run(
"main:app",
log_level="warning", # 只记录警告和错误
access_log=False # 关闭访问日志(或使用异步日志)
)
💡 常见问题
⚠️ 1. reload 和workers不能同时使用
uvicorn.run("main:app", reload=True, workers=4) # ❌ 报错
解决方案:
- 开发环境: 使用
reload=True,不设置workers - 生产环境: 使用
workers > 1,不设置reload
⚠️ 2. 传入实例无法使用热重载
uvicorn.run(app, reload=True) # ❌ reload 无效
解决方案:
uvicorn.run("main:app", reload=True) # ✅ 使用字符串路径
⚠️ 3. 性能优化依赖未安装
WARNING: Using pure-Python implementation
解决方案:
pip install uvloop httptools
⚠️ 4. 反向代理配置
当应用部署在 Nginx/Caddy 等反向代理后,需要配置:
uvicorn.run(
"main:app",
proxy_headers=True, # 信任代理头
forwarded_allow_ips="*" # 允许的代理IP
)
340

被折叠的 条评论
为什么被折叠?



