一篇真正“保姆级”的Uvicorn操作指南,涵盖从零基础安装、各种启动方式、后台运行、与框架结合、生产环境部署、性能优化、常见问题排错等,一本随时可查的手册。
后台启动、多进程、Gunicorn+Uvicorn、systemd守护、Docker部署… 你想要的全都有
很多 Python 开发者对异步服务器的认知停留在“很厉害但不会用”。
今天这篇文章,我将用最详细的步骤,带你彻底搞懂 Uvicorn——这个让 Python 接口性能起飞的核心工具。
本文涵盖:
- ✅ 什么是 Uvicorn,为什么它这么快
- ✅ 安装与基础启动(包括热重载)
- ✅ 后台启动的三种方式(nohup、screen、systemd)
- ✅ 与 FastAPI / Starlette 结合的最佳实践
- ✅ 生产环境部署:Gunicorn + Uvicorn、多进程、日志配置
- ✅ Docker 容器化部署
- ✅ 性能调优与常见问题排查
建议收藏,以后无论开发还是部署,随时可以查阅。
01 认识 Uvicorn:Python 异步服务器界的“闪电侠”
1.1 Uvicorn 是什么?
Uvicorn 是一个基于 ASGI(异步服务器网关接口) 的高性能 Python Web 服务器。
它使用 uvloop(基于 libuv 的事件循环)和 httptools(Node.js 同款 HTTP 解析器),性能远超传统的 WSGI 服务器(如 Gunicorn 的同步工作模式)。
核心优势:
- 异步支持:可以处理 WebSocket、HTTP/2 等长连接,并发能力极强。
- 闪电速度:基准测试中,Uvicorn 是 Python 最快的服务器之一。
- 生态融合:是 FastAPI、Starlette 等现代异步框架的官方推荐服务器。
1.2 同步 vs 异步,一张图看懂
| 模式 | 处理方式 | 并发能力 | 适用场景 |
|---|---|---|---|
| WSGI(同步) | 一个请求占一个线程,等待 I/O 时线程阻塞 | 受线程数限制,高并发下资源消耗大 | 简单 CRUD 应用 |
| ASGI(异步) | 一个线程可处理多个请求,I/O 等待时切换任务 | 极高,单线程可处理成千上万并发 | 高并发 API、WebSocket、实时服务 |
02 安装 Uvicorn
2.1 基础安装
pip install uvicorn
2.2 安装标准版(推荐)
标准版包含了 uvloop 和 httptools,性能更佳:
pip install 'uvicorn[standard]'
2.3 验证安装
uvicorn --version
输出类似 uvicorn, version 0.24.0 即成功。
03 第一个 Uvicorn 应用
3.1 最简 ASGI 应用
新建文件 app.py:
# app.py
async def app(scope, receive, send):
assert 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, Uvicorn!',
})
3.2 启动服务
uvicorn app:app
参数说明:app:app 表示 文件名:应用实例名。
访问 http://127.0.0.1:8000 即可看到输出。
3.3 开发模式(热重载)
uvicorn app:app --reload
代码修改后自动重启,极大提升开发效率。
3.4 指定端口和主机
uvicorn app:app --host 0.0.0.0 --port 8080
0.0.0.0 表示监听所有网络接口,允许外部访问。
04 后台启动 Uvicorn(三种方式)
生产环境中,我们通常需要让 Uvicorn 在后台运行,即使关闭终端也不中断。这里提供三种常用方法。
4.1 方式一:nohup(最简单)
nohup uvicorn app:app --host 0.0.0.0 --port 8000 > uvicorn.log 2>&1 &
nohup:忽略挂断信号> uvicorn.log:标准输出重定向到日志文件2>&1:错误输出也重定向到同一文件&:后台运行
查看进程:
ps aux | grep uvicorn
停止进程:
kill <PID>
4.2 方式二:使用 screen(可随时恢复)
# 安装 screen(如果未安装)
sudo apt install screen # Ubuntu/Debian
# 或 yum install screen # CentOS
# 创建一个名为 uvicorn 的会话
screen -S uvicorn
# 在 screen 中启动服务
uvicorn app:app --host 0.0.0.0 --port 8000
# 按 Ctrl+A 再按 D 分离会话(detach)
恢复会话:
screen -r uvicorn
停止:进入会话后按 Ctrl+C 停止进程,然后 exit 退出会话。
4.3 方式三:systemd 服务(生产级推荐)
创建 systemd 服务文件 /etc/systemd/system/uvicorn.service:
[Unit]
Description=Uvicorn ASGI server
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/path/to/your/app
Environment="PATH=/path/to/venv/bin"
ExecStart=/path/to/venv/bin/uvicorn app:app --host 0.0.0.0 --port 8000
Restart=always
[Install]
WantedBy=multi-user.target
User/Group:指定运行的用户组,不要用 rootWorkingDirectory:项目根目录Environment:虚拟环境路径Restart=always:进程退出后自动重启
启用并启动服务:
sudo systemctl daemon-reload
sudo systemctl enable uvicorn
sudo systemctl start uvicorn
查看状态:
sudo systemctl status uvicorn
查看日志:
sudo journalctl -u uvicorn -f
05 与 FastAPI / Starlette 结合
实际开发中,我们几乎不会直接写 ASGI 应用,而是使用 FastAPI 或 Starlette 框架。
5.1 安装 FastAPI
pip install fastapi
5.2 编写 FastAPI 应用
新建 main.py:
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello Uvicorn"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
# 脚本直接运行
if __name__ == "__main__":
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8000,
reload=True, # 开发模式
log_level="debug"
)
5.3 启动
命令行方式:
uvicorn main:app --reload
脚本方式:
python main.py
06 生产环境部署(Gunicorn + Uvicorn)
在生产环境,我们通常使用 Gunicorn 作为进程管理器,通过 uvicorn.workers.UvicornWorker 来运行 Uvicorn,这样既能利用 Gunicorn 的健壮进程管理,又能享受 Uvicorn 的异步性能。
6.1 安装依赖
pip install gunicorn uvicorn[standard]
6.2 启动命令
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
-w 4:工作进程数,通常设为 CPU 核心数 × 2 + 1-k uvicorn.workers.UvicornWorker:指定使用 Uvicorn 的工作类--bind:绑定地址和端口
6.3 配合 systemd
创建服务文件 /etc/systemd/system/gunicorn.service:
[Unit]
Description=Gunicorn + Uvicorn
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/path/to/your/app
Environment="PATH=/path/to/venv/bin"
ExecStart=/path/to/venv/bin/gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
Restart=always
[Install]
WantedBy=multi-user.target
启动同之前 systemd 操作。
07 日志配置
默认日志比较简单,生产环境需要更详细的日志(访问日志、错误日志等)。
7.1 命令行配置
uvicorn main:app --log-level info --access-log
--log-level:可选debug、info、warning、error、critical--access-log:开启访问日志
7.2 通过配置文件
创建 log_config.yaml:
version: 1
disable_existing_loggers: False
formatters:
default:
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
access:
format: "%(asctime)s - %(levelname)s - %(message)s"
handlers:
console:
class: logging.StreamHandler
formatter: default
stream: ext://sys.stdout
access_console:
class: logging.StreamHandler
formatter: access
stream: ext://sys.stdout
loggers:
uvicorn:
handlers: [console]
level: INFO
uvicorn.error:
level: INFO
uvicorn.access:
handlers: [access_console]
level: INFO
propagate: False
启动时指定:
uvicorn main:app --log-config log_config.yaml
08 Docker 部署 Uvicorn
8.1 编写 Dockerfile
FROM python:3.11-slim
WORKDIR /app
# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制代码
COPY . .
# 暴露端口
EXPOSE 8000
# 启动命令(注意使用 CMD 而不是 RUN)
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
8.2 requirements.txt
fastapi
uvicorn[standard]
8.3 构建并运行
# 构建镜像
docker build -t my-uvicorn-app .
# 运行容器(前台)
docker run -p 8000:8000 my-uvicorn-app
# 后台运行
docker run -d -p 8000:8000 --name myapp my-uvicorn-app
8.4 使用 docker-compose(生产级)
创建 docker-compose.yml:
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- ENVIRONMENT=production
restart: always
command: uvicorn main:app --host 0.0.0.0 --port 8000
启动:
docker-compose up -d
09 性能调优与注意事项
9.1 工作进程数
对于 Gunicorn+Uvicorn,-w 参数建议为 (2 * CPU核心数) + 1。
如果使用 Uvicorn 直接多进程(--workers),同样遵循此规则。
9.2 内存与连接限制
Uvicorn 默认不限制并发连接数,在高流量场景下建议设置:
uvicorn main:app --limit-concurrency 1000
每个工作进程的最大并发连接数。
9.3 禁用自动重载(生产环境)
--reload 会降低性能,生产环境必须移除。
9.4 使用 Nginx 作为反向代理
Nginx 可以处理静态文件、负载均衡和 SSL 终结。
示例 Nginx 配置:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
9.5 避免在异步代码中使用阻塞调用
如果在异步视图函数中使用了 time.sleep()、requests.get() 等阻塞操作,会阻塞事件循环。应使用 asyncio.sleep() 和 httpx.AsyncClient。
10 常见问题排查
Q1:端口被占用
错误信息:[Errno 98] Address already in use
解决:换端口,或 kill 占用端口的进程:
sudo lsof -i :8000
sudo kill -9 <PID>
Q2:应用无法访问
- 检查防火墙:
sudo ufw allow 8000 - 确保绑定
0.0.0.0而不是127.0.0.1
Q3:日志没有输出
- 确认
--log-level设置正确 - 检查日志配置文件路径是否正确
Q4:内存不断增长
-
可能是代码中存在内存泄漏(例如全局变量不断累积)
-
使用
--limit-max-requests定期重启工作进程:uvicorn main:app --limit-max-requests 1000
Q5:WebSocket 连接失败
-
确保 Nginx 配置支持 WebSocket:
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
结语
从零基础到生产部署,Uvicorn 的每一个细节我都尽力写全了。
无论你是个人开发者,还是在团队中负责后端架构,这份手册都能帮你少踩无数坑。
如果你觉得这篇文章对你有帮助,欢迎点赞、在看、转发,让更多人用上 Python 的异步力量。
如果还有未覆盖到的场景,欢迎评论区留言,我会持续更新。