直接用 uvicorn main:app --reload 上生产等于埋雷:它单进程、监听文件变更、无超时、不处理慢连接,且--reload与--workers互斥;生产必须关闭--reload,用Gunicorn管理Uvicorn Worker,并显式指定--host 0.0.0.0、合理设workers数、配置超时与日志。

直接用 uvicorn main:app --reload 上生产,等于给服务埋雷——它会监听文件变更、只启单进程、不设超时、不处理慢连接,出问题不是“会不会”,而是“什么时候”。
别用 --reload,也别让它和 --workers 同时出现
这两个参数互斥,但更关键的是:--reload 本质是开发辅助功能,依赖 inotify 或 watchdog 监控文件系统。生产环境里代码由 CI/CD 推送,文件变动不该触发重启;且该机制在容器中常失效,白白消耗 CPU 做无用监听。一旦误操作覆盖了代码文件,主进程可能瞬间退出,导致请求中断。
-
--reload只应在本地开发时启用,CI/CD 部署后必须关闭 - 若需热更新,应走滚动重启(如 Kubernetes 的 rolling update)或用 Gunicorn 管理 Uvicorn Worker
- 使用
--workers时,Uvicorn 自动禁用 reload,但显式写出来反而容易让人忽略冲突
worker 数量不能硬写成 4,得看 CPU 和业务类型
盲目设 --workers 4 是常见懒政。Uvicorn 的 worker 是进程级的,每个 worker 独占一个 CPU 核心跑事件循环。设多了,I/O 密集型服务能吞更多并发;但 CPU 密集型任务(比如图像处理、复杂计算)反而因频繁进程切换拖慢整体性能。
- I/O 密集型(如数据库查询、HTTP 调用多):可用
multiprocessing.cpu_count() * 2 + 1作为起点 - CPU 密集型:建议从
cpu_count()开始,再根据top或htop观察 CPU steal 和上下文切换次数调整 - Docker 容器里要读
/sys/fs/cgroup/cpu.max或cpusets,而不是宿主机核数
不配 --host 0.0.0.0 就等于没对外暴露服务
Uvicorn 默认绑定 127.0.0.1,这在开发机上没问题,但一进生产环境,Nginx 或负载均衡器发来的请求全被拒之门外。错误日志里往往只显示 “connection refused”,排查时容易绕远路查网络策略或防火墙,其实只是监听地址错了。
Uvicorn 0.52.1 是 Python ASGI Web 服务器,提供异步应用服务及 WebSocket 支持,常用于 FastAPI、Starlette 等应用的开发和部署。本下载为官方 PyPI 通用 wheel 包,可使用 pip 安装,并由包管理器处理所需依赖。
- 必须显式加
--host 0.0.0.0,否则外部流量进不来 - 不要写
--host localhost,它解析结果仍是127.0.0.1 - 如果用 UNIX socket(如配合 Nginx),则用
--uds /tmp/uvicorn.sock,此时--host和--port会被忽略
超时、连接队列、日志输出这些参数不设就等于裸奔
默认配置下,Uvicorn 对单个请求没硬性超时,等待队列长度只有 100,访问日志不输出到 stdout —— 这些在压测或突发流量时都会变成故障点。比如慢 SQL 拖住一个 worker,其他请求就在 backlog 里排队,直到客户端先超时断开。
-
--timeout-keep-alive 5:控制空闲连接保持时间,避免被中间设备(如云 LB)静默断连 -
--limit-concurrency 1000:限制单 worker 并发请求数,防止单个进程过载 -
--backlog 2048:调大 TCP 连接等待队列,尤其在 Linux 上可缓解 SYN flood 类压力 -
--access-log和--log-level info必须开启,容器环境记得用--access-log -输出到 stdout,方便日志采集
最易被忽略的一点:Uvicorn 本身不处理 SSL 终止、静态文件、缓冲慢客户端,这些必须交给 Nginx 或 Traefik;只靠它自己扛公网流量,等于把门锁拆了装在窗户上。










