Uvicorn不可直接暴露公网,必须由Nginx反向代理:proxy_pass须指向127.0.0.1:8000(非localhost),透传X-Forwarded-*及Upgrade/Connection头,统一设timeout为300秒,SSL终止在Nginx层,禁用Uvicorn HTTPS。

Uvicorn 不能直接暴露给公网,必须用 Nginx 做反向代理——否则会丢 WebSocket 头、超时炸裂、静态文件慢三倍,还可能被扫描器打穿端口。
proxy_pass 必须指向 uvicorn 监听的本地地址
Nginx 不是“和 Uvicorn 打交道”,而是把请求原样转给它。Uvicorn 默认只监听 127.0.0.1:8000(或 --host 0.0.0.0 --port 8000),所以 proxy_pass 必须写成 http://127.0.0.1:8000,不能写成 http://localhost:8000(某些系统里 localhost 解析走 IPv6,Uvicorn 没监听 ::1 就直接 502)。
- 确认 Uvicorn 真正在跑:
ss -tuln | grep :8000或lsof -i :8000 - 如果用了 UNIX socket(比如
--uds /tmp/uvicorn.sock),Nginx 配置要改用proxy_pass http://unix:/tmp/uvicorn.sock;,且确保 Nginx worker 用户有读写权限 - 别在
proxy_pass后面加多余路径,比如http://127.0.0.1:8000/api—— 这会让 Uvicorn 收到带/api前缀的 path,而你的 FastAPI/Sanic 路由没配这个前缀,结果全 404
必须透传 X-Forwarded-* 和 Upgrade 头
Uvicorn 需要知道真实客户端 IP、协议(HTTP/HTTPS)、Host,否则 request.client.host 变成 127.0.0.1,url_for 生成的链接变成 http:// 开头,WebSocket 升级失败直接断连。
Uvicorn 0.52.1 是 Python ASGI Web 服务器,提供异步应用服务及 WebSocket 支持,常用于 FastAPI、Starlette 等应用的开发和部署。本下载为官方 PyPI 通用 wheel 包,可使用 pip 安装,并由包管理器处理所需依赖。
- 至少加这四行:
proxy_set_header X-Forwarded-For $remote_addr;、proxy_set_header X-Forwarded-Proto $scheme;、proxy_set_header X-Forwarded-Host $host;、proxy_set_header X-Forwarded-Port $server_port; - WebSocket 场景下必须加:
proxy_set_header Upgrade $http_upgrade;和proxy_set_header Connection "upgrade";,缺一不可 - 如果后端用了
TrustedHostMiddleware(如 FastAPI),$host必须在allowed_hosts列表里,否则返回 400
timeout 和 buffer 设置不当会导致 502/504
Uvicorn 默认 read timeout 是 60 秒,但 Nginx 的 proxy_read_timeout 默认只有 60 秒,一旦后端处理稍慢(比如大文件上传、LLM 推理),Nginx 就先断开连接,报 504 Gateway Timeout。
- 建议统一设为 300 秒:
proxy_connect_timeout 300;、proxy_send_timeout 300;、proxy_read_timeout 300; - 大请求体(如文件上传)要调大:
client_max_body_size 100M;,不然直接 413 Request Entity Too Large - 避免缓冲区溢出:
proxy_buffering on;(默认开启),但若后端流式响应(SSE、streaming JSON),可关掉:proxy_buffering off;,否则 Nginx 会攒满 buffer 才发给浏览器
SSL 终止必须在 Nginx 层完成
不要让 Uvicorn 自己扛 HTTPS——它不擅长证书热加载、OCSP Stapling、TLS 版本协商,而且多进程下 SSL 握手开销翻倍。
- Nginx 配置里加
listen 443 ssl http2;,然后指定证书:ssl_certificate /path/to/fullchain.pem;、ssl_certificate_key /path/to/privkey.pem; - 强制跳转 HTTPS:
return 301 https://$host$request_uri;放在listen 80的 server 块里 - Uvicorn 完全不用碰
--ssl-keyfile或--ssl-certfile,保持纯 HTTP 启动即可 - 注意:如果用了 Let’s Encrypt,
certbot自动续期后要 reload Nginx(nginx -s reload),而不是重启,避免连接中断
最容易被忽略的是 Nginx worker 进程数与 Uvicorn workers 的协同——Nginx 默认 worker_processes auto,但若你只启了 1 个 Uvicorn worker,Nginx 却开了 8 个 worker,大量请求会排队等那唯一一个后端,CPU 却没跑满。实际部署前,先用 ab 或 wrk 压测,看瓶颈到底在 Nginx 还是 Uvicorn。

















