Uvicorn实操教程

2025博客之星年度评选已开启 10w+人浏览 1.5k人参与

Uvicorn实操教程

📖 一. Uvicorn概要

Uvicorn是一个基于uvloophttptools构建的高性能 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 基础参数

参数类型说明默认值
appstr/object应用路径或实例必填
hoststr绑定主机地址"127.0.0.1"
portint监听端口8000

🛠️ 3.2 开发参数

参数类型说明注意事项
reloadbool代码变更自动重启workers 互斥
reload_dirslist监控目录列表配合 reload 使用
reload_includeslist监控文件模式["*.py", "*.yaml"]
reload_excludeslist排除文件模式["*.pyc"]

🚀 3.3 生产参数

参数类型说明推荐值
workersint工作进程数CPU 核心数 * 2 + 1
loopstr事件循环"uvloop"
httpstrHTTP 实现"httptools"
proxy_headersbool信任代理头反向代理场景设为 True
forwarded_allow_ipsstr允许的代理 IP具体 IP 或 "*"

📊 3.4 日志参数

参数类型说明可选值
log_levelstr日志级别critical/error/warning/info/debug/trace
access_logbool访问日志True/False
use_colorsbool彩色日志True/False
log_configdict/str自定义日志配置日志配置文件路径或字典

🔌 3.5 连接参数

参数类型说明默认值
timeout_keep_aliveintKeep-Alive 超时(秒)5
limit_concurrencyint最大并发连接数None(无限制)
limit_max_requestsint进程重启前最大请求数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 进程守护

生产环境建议用 supervisorsystemd 守护进程,防止服务意外退出。

示例 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
)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值