Gunicorn不能直接对外提供生产级HTTP服务,必须搭配Nginx:Gunicorn仅负责运行Python应用、管理worker进程并响应WSGI请求,不处理HTTPS、静态文件、限流、防攻击等网络层任务;Nginx则承担反向代理、SSL终止、静态资源服务、请求头传递、超时控制等职责,二者分工明确、缺一不可。

gunicorn 本身不能直接对外提供生产级 HTTP 服务,必须搭配 nginx 才能跑通真实流量场景。
你本地用 flask run 或 python manage.py runserver 能打开页面,不代表它能上线——Werkzeug 和 Django 自带服务器明确标注 "This is not for production use.",它们既不处理并发连接,也不防慢速攻击,更不会自动回收崩溃进程。
gunicorn 的角色很清晰:只管运行你的 Python 应用、拉起 worker 进程、响应 WSGI 请求。它不解析 HTTPS、不缓存静态文件、不压缩响应、不校验请求头长度、不拦截恶意扫描——这些都不是它的责任边界。
nginx 是那个真正站在公网门口的人:它把 <a href="https://www.php.cn/link/ff451b4a456150649bc16b979c93a383">https://www.php.cn/link/ff451b4a456150649bc16b979c93a383</a> 直接返回文件,绕过 Python;把用户 IP 写进 X-Real-IP 头再转给 gunicorn;在后端卡住时返回 503 页面而不是让浏览器一直转圈;用 proxy_read_timeout 控制最长等待时间,避免一个慢请求拖垮全部连接。
立即学习“Python免费学习笔记(深入)”;
常见错误现象包括:
-
502 Bad Gateway:gunicorn没起来,或nginx配的proxy_pass地址连不上 -
request.remote_addr总是127.0.0.1:nginx没配proxy_set_header X-Real-IP $remote_addr,且 Python 框架没启用信任代理头逻辑 - 静态资源 404 或被 Python 处理:
nginx的location /static/规则没写对路径,或没加alias而用了root
为什么不能只用 gunicorn 绑定 0.0.0.0:80?
gunicorn 默认监听 TCP 端口,但直接暴露在公网有硬伤:
- 它没有内置 SSL 终止能力,没法原生支持 HTTPS(得靠反向代理或额外套一层 stunnel)
- 它不支持虚拟主机(server_name),多个域名共用一台机器时无法区分路由
- 它无法按 MIME 类型设置缓存头,静态文件缓存策略只能全靠 Python 层硬编码
- 它对大上传体(如文件上传)缺乏流式控制,容易被恶意构造的超长请求打穿内存
而 nginx 做这些事是内建能力,一行 client_max_body_size 10M 就能拦住超大 POST,不需要改一行 Python 代码。
gunicorn worker 数设成 2 × CPU 核心数 反而变慢?
这是同步阻塞模型的典型陷阱。每个 sync worker 在等待数据库响应、HTTP 外部调用或文件读写时,会全程占用一个 OS 线程+Python 解释器线程,不释放 GIL,也不让出 CPU。
实测中:
- worker 数超过 4~8 后,上下文切换开销和内存争用会明显抬高延迟
- 若应用大量依赖
requests.get()等 I/O 操作,建议优先换worker_class = "gevent"或"uvicorn.workers.UvicornWorker"(后者仅限 ASGI) - 单纯增加
workers参数却不换模型,只是把瓶颈从“CPU 空转”转移到“内存耗尽”或“连接池打满”
nginx 转发后日志里全是 "Connection reset by peer"
这不是错误,是常态。它表示客户端(浏览器关闭标签页、移动端切后台、运营商中间设备 kill 长连接)在响应还没发完时主动断开了 TCP 连接。
gunicorn 把它记为 warning,但 Python 层完全感知不到——try/except 捕获不到,after_request 钩子也不会触发。别把它当崩溃日志去排查,除非伴随大量 500 或 timeout。
真正要盯的是:
-
gunicorn的timeout是否小于 Nginx 的proxy_read_timeout(必须前者 ≤ 后者,否则 Nginx 先断连) -
nginxaccess log 中持续出现499状态码(表示客户端主动中断) -
gunicornerror log 中是否混杂真实异常(如OperationalError、MemoryError)
最易被忽略的一点:UNIX socket 比 TCP 更快,但权限配置稍麻烦——nginx worker 进程用户(通常是 www-data)必须对 .sock 文件有读写权限,且 gunicorn 启动命令里 --chown 参数不能漏。


















