正确配置为 proxy_pass http://unix:/path/to/app.sock 并配合 upstream + keepalive,可提升短连接 QPS 30%+、P99 延迟减半;需注意协议前缀、路径权限、末尾斜杠语义、keepalive 参数及模块匹配。

直接结论:用 proxy_pass http://unix:/path/to/app.sock 替代 proxy_pass http://127.0.0.1:8000,再配 upstream + keepalive,实测短连接 QPS 可提升 30%+,P99 延迟压降一半以上——但配置错一个字符就 502 或 403。
proxy_pass unix socket 必须带 http:// 协议前缀
很多人写成 proxy_pass unix:/var/run/app.sock,Nginx 启动直接报错:invalid URL prefix。Unix Socket 在 HTTP 模块里不是“地址”,而是 URL 的一部分,必须显式声明协议。
-
proxy_pass http://unix:/var/run/app.sock✅ 正确(注意http://后紧接unix:,中间无空格) -
proxy_pass unix:/var/run/app.sock❌ 报错,Nginx 认为这不是合法 URL -
proxy_pass http://unix:/var/run/app.sock/✅ 可用,但末尾/会触发 URI 重写逻辑(见下一条)
路径必须是绝对路径;socket 文件需由后端进程(如 Uvicorn、Gunicorn)提前创建并设好权限(Nginx worker 用户需有读写权限)。
location 中 proxy_pass 末尾斜杠决定 URI 是否透传
这个细节不看日志根本发现不了——后端收不到预期路径,或 404,或路由错乱。
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
-
location /api/ { proxy_pass http://unix:/var/run/app.sock/; }→ 请求/api/v1/users被转发为/v1/users(/api/被剥离) -
location /api/ { proxy_pass http://unix:/var/run/app.sock; }→ 同样请求被转发为/api/v1/users(完整透传) - 若后端是 FastAPI/Flask,默认不处理
/api/前缀,第一种写法才合理;若后端已按/api/分组路由,则第二种更自然
别靠猜,用 curl -v 看后端 access log 或加 proxy_set_header X-Debug-URI $request_uri; 辅助验证。
启用 keepalive 复用 Unix Socket 连接(否则性能白搭)
默认情况下,每个 HTTP 请求都新建 + 关闭一次 Unix Socket 连接,系统调用开销巨大。不配 upstream + keepalive,UDS 的优势几乎全被抵消。
- 必须用
upstream块声明后端,不能直接在location里写proxy_pass http://unix:...:
upstream backend {
server unix:/var/run/app.sock;
keepalive 32;
}
location 中引用:proxy_pass http://backend;(不是 unix:)proxy_http_version 1.1; 和 proxy_set_header Connection '';
keepalive 32 是经验值:太小(如 4)复用率低;太大(如 256)可能耗尽 worker 进程的文件描述符(worker_rlimit_nofile 要同步调高)区分 ngx_http_proxy_module 和 ngx_stream_proxy_module 的 proxy_pass
写错模块位置,配置直接无效——尤其容易在 TCP 层代理(如 MySQL、Redis)时误用 HTTP 模块的 proxy_pass。
- HTTP/HTTPS/WebSocket 代理 → 用
ngx_http_proxy_module,proxy_pass只能在location里,且必须带协议(http://或https://) - TCP/UDP 端口转发(如数据库、自定义二进制协议)→ 用
ngx_stream_proxy_module,proxy_pass只能在server块里,语法是纯地址:proxy_pass unix:/tmp/db.sock;(无协议前缀) - 混用会报错:
"proxy_pass" directive is not allowed here或启动失败
Unix Socket 路径本身没区别,但模块语义和上下文约束完全不同——看清楚你代理的是 HTTP 流量还是裸 TCP 流量,再选模块。

















