第1章:Uvicorn 简介

1.1 什么是 Uvicorn

Uvicorn 是一个 Python ASGI 服务器,用于运行支持异步协议的 Web 应用。它常见于 FastAPI、Starlette、Quart 等 ASGI 框架场景,也可以直接运行原生 ASGI 应用。

相比传统 WSGI 服务器,Uvicorn 面向异步 I/O 设计,支持 HTTP/1.1 与 WebSocket,并提供热重载、多进程、日志配置、代理头处理、HTTPS 等能力。

1.2 Uvicorn 的定位

开发阶段:本地启动 ASGI 应用,配合 --reload 实现代码热更新

  • 测试阶段:快速验证服务入口、接口行为和日志输出
  • 部署阶段:作为生产服务进程本身运行,或作为 Gunicorn / 反向代理体系中的一部分

1.3 核心特性

  • 支持 ASGI:适合异步 Python Web 应用
  • 启动方式灵活:支持命令行和代码调用两种方式
  • 配置完整:监听地址、协议栈、日志、超时、并发、TLS 都可配置
  • 支持多进程:可以通过 --workers 开启多个工作进程
  • 开发体验好:配合 watchfiles 时支持更细粒度的热重载

第2章:安装指南

2.1 基础安装

Uvicorn 发布在 PyPI,可安装最小依赖版本:

pip install uvicorn

最小安装通常会包含:

  • click:命令行接口支持
  • h11:纯 Python 的 HTTP/1.1 实现

2.2 标准增强安装

如果希望一次安装常用增强依赖,推荐使用标准扩展:

pip install "uvicorn[standard]"

uvicorn[standard] 通常会额外包含:

  • uvloop:高性能事件循环,性能更好,但不兼容 Windows
  • httptools:更高性能的 HTTP 解析器
  • websockets:WebSocket 支持
  • watchfiles:热重载文件监控
  • python-dotenv:支持 --env-file
  • PyYAML:支持 YAML 日志配置
  • colorama:Windows 终端彩色输出支持

2.3 什么时候装最小版,什么时候装标准版

  • 最小版:只想快速跑起来,或者部署环境强调依赖最少
  • 标准版:开发环境、本地调试、需要热重载、WebSocket 或更好的日志体验

对于大多数开发场景,建议直接使用标准版。

第3章:第一个 Uvicorn 应用

3.1 原生 ASGI 应用示例

创建 main.py:

async def app(scope, receive, send):
assert scope["type"] == "http"

body = b"Hello, Uvicorn!"

await send(
{
"type": "http.response.start",
"status": 200,
"headers": [
(b"content-type", b"text/plain; charset=utf-8"),
(b"content-length", str(len(body)).encode("ascii")),
],
}
)
await send(
{
"type": "http.response.body",
"body": body,
}
)

3.2 命令行启动

在项目根目录执行:

uvicorn main:app

这里的 main:app 表示:

  • main:Python 模块名,即 main.py
  • app:模块中的 ASGI 应用对象

默认监听:

  • 主机:127.0.0.1
  • 端口:8000

打开浏览器访问 http://127.0.0.1:8000 即可看到结果。

3.3 常用启动形式

指定主机和端口

uvicorn main:app --host 0.0.0.0 --port 9000

开发模式热重载

uvicorn main:app --reload

使用应用工厂

如果应用通过工厂函数返回:

def create_app():
return app

则启动命令为:

uvicorn --factory main:create_app

第4章:运行方式

4.1 命令行方式

Uvicorn 最常见的使用方式是直接通过命令行运行:

uvicorn main:app --host 127.0.0.1 --port 8000

适合场景:

  • 本地开发
  • 容器启动命令
  • 测试环境直接拉起服务

4.2 代码方式

如果要在 Python 代码中控制服务启动,可以使用 uvicorn.run():

import uvicorn

async def app(scope, receive, send):

...

if __name__ == "__main__":
uvicorn.run("main:app", host="127.0.0.1", port=5000, log_level="info")

注意事项:

  • 如果要使用 reload=True 或 workers > 1,官方建议把 uvicorn.run(...) 放在 if name == "__main__": 保护块中
  • 如果直接传入应用实例而不是导入字符串,则不能与多进程和热重载良好配合,因此更推荐使用 main:app 这种导入字符串形式

4.3 细粒度控制:Config 与 Server

如果需要更精细地控制服务生命周期,可使用 uvicorn.Config 与 uvicorn.Server:

import uvicorn

def main():
config = uvicorn.Config("main:app", host="127.0.0.1", port=5000, log_level="info")
server = uvicorn.Server(config)
server.run()

if __name__ == "__main__":
main()

如果当前已经处于异步环境中,可调用 await server.serve()。

第5章:配置方法总览

5.1 三种配置来源

根据官方文档,Uvicorn 配置主要有三种方式:

  • 命令行参数
  • uvicorn.run() 关键字参数
  • 环境变量,变量名前缀为 UVICORN_

例如:

set UVICORN_HOST=0.0.0.0

set UVICORN_PORT=8000

uvicorn main:app

优先级规则:

  • 命令行参数优先级最高
  • uvicorn.run() 显式参数也高于环境变量

5.2 --env-file 的作用边界

--env-file 常被误解。它主要用于给你的 ASGI 应用加载环境变量,而不是专门配置 Uvicorn 自身。

也就是说:

  • 应用自己的配置项可以通过 .env 进入进程环境
  • UVICORN_* 这类配置不应依赖 --env-file

第6章:常用配置项

6.1 应用定位

  • APP:应用入口,格式为 模块:对象
  • --factory:把入口当成工厂函数调用
  • --app-dir :把指定目录加入 Python 路径后再查找应用

示例:

uvicorn src.main:app --app-dir .

6.2 监听与绑定

--host:监听地址,默认 127.0.0.1

--port:监听端口,默认 8000

--uds:绑定 Unix Domain Socket

--fd:从已有文件描述符接管套接字

典型示例:

uvicorn main:app --host 0.0.0.0 --port 8000

如果希望局域网设备访问本机服务,通常需要把地址绑定到 0.0.0.0。

6.3 开发模式

  • --reload:开启自动重载
  • --reload-dir:指定监听目录,可多次传入
  • --reload-delay:重载检测间隔,默认 0.25
  • --reload-include:额外包含的文件模式
  • --reload-exclude:排除的文件模式

注意:

  • --reload 与 --workers 互斥,不能同时使用
  • 若未安装 watchfiles,Uvicorn 只能基于 *.py 文件修改时间做基础重载
  • 安装 watchfiles 后,--reload-include 和 --reload-exclude 才能生效

6.4 日志

  • --log-level:日志级别,可选 critical、error、warning、info、debug、trace
  • --access-log / --no-access-log:开启或关闭访问日志
  • --use-colors / --no-use-colors:彩色日志
  • --log-config:读取日志配置文件,支持 .ini、.json、.yaml

使用 YAML 日志配置时,需要项目里安装 PyYAML,或者直接安装 uvicorn[standard]。

6.5 实现层配置

  • --loop:事件循环实现,可选 auto、asyncio、uvloop
  • --http:HTTP 协议实现,可选 auto、h11、httptools
  • --ws:WebSocket 实现,可选 auto、none、websockets、websockets-sansio、wsproto
  • --lifespan:生命周期协议,可选 auto、on、off
  • --interface:接口类型,可选 auto、asgi3、asgi2、wsgi

平台与兼容性建议:

  • Windows 上不要强依赖 uvloop
  • 若追求最强兼容性,可显式指定 --loop asyncio --http h11
  • WSGI 模式会禁用 WebSocket,且官方已提示原生 WSGI 支持处于弃用路径,建议改用 a2wsgi

6.6 HTTP 与代理

  • --proxy-headers / --no-proxy-headers:是否读取代理头
  • --forwarded-allow-ips:指定可信代理来源
  • --root-path:设置 ASGI 的 root_path
  • --server-header / --no-server-header
  • --date-header / --no-date-header
  • --header Name:Value:添加默认响应头

如果服务部署在反向代理之后,务必只信任真正可控的代理地址;把 --forwarded-allow-ips 配成 * 之前,需要确认上游代理会清洗并重写转发头。

6.7 HTTPS

常用 TLS 参数:

  • --ssl-keyfile
  • --ssl-certfile
  • --ssl-keyfile-password
  • --ssl-version
  • --ssl-cert-reqs
  • --ssl-ca-certs
  • --ssl-ciphers

本地测试 HTTPS 示例:

uvicorn main:app --port 5000 --ssl-keyfile=./key.pem --ssl-certfile=./cert.pem

6.8 资源限制与超时

--limit-concurrency:最大并发连接或任务数,超出可返回 503

--backlog:等待连接队列长度

--limit-max-requests:单进程最大请求数

--limit-max-requests-jitter:最大请求数的抖动值,避免同时重启

--timeout-keep-alive:Keep-Alive 超时

--timeout-graceful-shutdown:优雅关闭等待时间

--timeout-worker-healthcheck:worker 健康检查超时

这些选项更偏生产调优,在高并发或长时间运行场景下比较重要。

第7章:开发阶段常用命令

7.1 最常见的本地开发命令

uvicorn main:app --reload

7.2 指定多个热重载目录

uvicorn main:app --reload --reload-dir src --reload-dir app

7.3 指定日志级别

uvicorn main:app --reload --log-level debug

7.4 指定 WebSocket 或 HTTP 实现

uvicorn main:app --ws wsproto --http h11

7.5 从子目录加载应用

uvicorn main:app --app-dir src

第8章:生产部署建议

8.1 生产模式基本原则

官方部署文档给出的通用建议可以概括为:

  • 本地开发使用 uvicorn --reload
  • 生产环境使用进程管理方式运行
  • 自建部署通常建议放在 Nginx 之后
  • 更上层还可以放 CDN 或云负载均衡

8.2 直接使用 Uvicorn 多进程

Uvicorn 内置多进程管理能力:

uvicorn main:app --workers 4 --host 0.0.0.0 --port 8000

特点:

  • 适合较轻量的生产部署
  • Windows 也可工作,因为其多进程模型基于 spawn
  • 不能和 --reload 同时使用

8.3 与 Gunicorn 协作

官方文档仍然介绍了 Gunicorn 方案,但同时标注:

  • uvicorn.workers 模块已弃用
  • 后续推荐转向 uvicorn-worker 包

如果团队已有 Gunicorn 体系,可以继续关注官方迁移方向;如果是纯 Windows 环境,一般不会选择 Gunicorn 作为主方案。

8.4 放在 Nginx 后面

Nginx 常用于:

  • 静态资源处理
  • 缓冲慢请求
  • 统一入口与域名配置
  • WebSocket 代理
  • HTTPS 终止

Uvicorn 支持通过 --uds 绑定 Unix Domain Socket,再由 Nginx 反代过去。不过这类方式更常见于 Linux 服务器。

8.5 反向代理头配置

如果部署在 Nginx、云负载均衡、Ingress、CDN 之后,需要正确处理:

  • X-Forwarded-For
  • X-Forwarded-Proto

否则应用层拿到的客户端 IP、协议类型可能不正确。

8.6 HTTPS 建议

  • 生产环境通常由 Nginx、Ingress 或云负载均衡做 TLS 终止
  • 直接让 Uvicorn 挂证书更适合简单场景或本地测试
  • 如果自行配 TLS,证书建议使用可信 CA,如 Let's Encrypt

第9章:搭配 uv 的使用方式

这一章结合本仓库已有的 uv 使用方式,说明如何用 uv 来管理和运行 Uvicorn。

9.1 用 uv 安装 Uvicorn

安装为运行依赖

如果项目需要启动 Web 服务,建议把 Uvicorn 加入项目依赖:

uv add uvicorn

如果开发阶段需要热重载、.env、YAML 日志等增强能力,推荐直接安装标准扩展:

uv add "uvicorn[standard]"

执行后,uv 会:

  • 安装依赖到当前项目虚拟环境
  • 更新 pyproject.toml
  • 更新 uv.lock

安装为开发依赖

如果 Uvicorn 只用于本地调试,不作为生产运行依赖,也可以放到开发依赖中:

uv add --dev "uvicorn[standard]"

9.2 用 uv 运行 Uvicorn

uv 不要求你先手动激活虚拟环境,最常见方式是:

uv run uvicorn main:app --reload

这条命令的意义是:

  • 使用当前项目的虚拟环境
  • 查找其中安装的 uvicorn
  • 启动 main:app
  • 开启热重载

这也是最推荐的日常开发方式,因为不依赖终端是否已激活 .venv。

9.3 用 uv 运行包内模块

如果应用代码位于包结构内,例如:

quant_local/

web/

main.py

可以这样运行:

uv run uvicorn quant_local.web.main:app --reload

9.4 与本仓库工作流配合的建议

本仓库当前已经采用 pyproject.toml 和 uv 管理依赖,因此推荐保持一致:

  • 新增 Web 服务依赖时使用 uv add
  • 本地启动服务时使用 uv run uvicorn ...
  • 团队协作时提交 uv.lock,保证依赖版本一致
  • 若需要 .env 或更强热重载能力,统一使用 uvicorn[standard]

9.5 常见组合命令

本地开发

uv add --dev "uvicorn[standard]"
uv run uvicorn main:app --reload --host 127.0.0.1 --port 8000

局域网联调

uv run uvicorn main:app --reload --host 0.0.0.0 --port 8000

生产多进程

uv add uvicorn
uv run uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4

9.6 Windows 环境补充说明

当前工作环境是 Windows,建议注意:

  • uvicorn[standard] 中的 uvloop 在 Windows 上不可用,这属于正常情况
  • 彩色日志支持通常由 colorama 提供
  • 如果在 WSL 中使用热重载,官方提到某些情况下需要设置 WATCHFILES_FORCE_POLLING

第10章:常见问题

10.1 为什么 --reload 不生效

常见原因:

  • 没有安装 watchfiles,只能做基础的 *.py 轮询检查
  • 监听目录不正确,需要加 --reload-dir
  • 在 WSL 下文件事件传递异常,需要额外设置轮询

10.2 为什么 --reload 和 --workers 不能一起用

因为一个偏开发期单进程重载,一个偏生产期多进程管理,官方明确将二者设为互斥。

10.3 为什么推荐使用 main:app 而不是直接传入对象

因为导入字符串方式更适合:

  • 多进程模式
  • 热重载模式
  • 统一启动入口

10.4 --env-file 为什么没把 UVICORN_PORT 生效

因为 --env-file 主要服务于应用自身环境变量,不是推荐用来驱动 UVICORN_* 配置的方式。

10.5 什么时候需要 --proxy-headers

当应用运行在反向代理之后,并且你希望应用正确识别真实客户端 IP 和协议时需要。但必须配合可信代理范围设置,不能无条件信任所有来源。

第11章:命令参考速查

11.1 基础命令


uvicorn main:app

uvicorn main:app --reload

uvicorn main:app --host 0.0.0.0 --port 8000

uvicorn --factory main:create_app

11.2 生产相关


uvicorn main:app --workers 4

uvicorn main:app --ssl-keyfile=./key.pem --ssl-certfile=./cert.pem

uvicorn main:app --limit-concurrency 1000 --timeout-keep-alive 10

11.3 搭配 uv

uv add uvicorn
uv add "uvicorn[standard]"
uv add --dev "uvicorn[standard]"
uv run uvicorn main:app --reload
uv run uvicorn main:app --workers 4 --host 0.0.0.0 --port 8000

第12章:实践建议总结

12.1 开发环境建议

  • 优先安装 uvicorn[standard]
  • 启动命令优先使用 uv run uvicorn ...
  • 使用 --reload
  • 需要更细粒度监控时补充 --reload-dir

12.2 生产环境建议

  • 不使用 --reload
  • 用 --workers 或进程管理器提升稳定性
  • 放在反向代理之后
  • 明确配置可信代理范围
  • 在高负载场景下配置并发、超时、最大请求数等参数

12.3 团队协作建议

  • 统一采用 uv 管理依赖
  • 提交 uv.lock
  • 将服务启动命令写入 README 或脚本
  • 把开发命令与生产命令分开管理,避免误用

参考来源

标签: none

添加新评论