Dify 卡在入口?Gunicorn + Nginx 的正确打开方式
网上教程都让你把
SERVER_WORKER_AMOUNT设成 8。但你用的是 gevent 模式啊------多开的 Worker 除了吃内存,什么都没干。📌 适用版本:Dify v1.9.x --- e-1.15.0 | 最后更新:2026-07-03
⚠️ Dify 版本迭代频繁,部分参数默认值可能随新版变化。本文发布时已对照官方最新文档校准,若发现配置项与你当前版本不一致,请以
docker/.env中的实际值为准,并查阅 官方环境变量文档。
🧭 本文是「Dify 并发急救手册」系列第 2 篇。如果你还没看过第 1 篇的 6 层瓶颈诊断框架,建议先读------你会知道本文解决的是 6 层中的第 1 层(HTTP 接入层)和第 6 层(数据库连接池)的联动问题。
一个被传烂了的公式
你在 CSDN、百度、甚至一些付费教程里,大概率见过这句话:
"Gunicorn Worker 数 = CPU 核数 × 2 + 1"
然后你照着做,8 核服务器设了 17 个 Worker。
这个公式没错------但它是给同步模式用的。
Dify 默认用的是 gevent 异步模式。它不是「一个 Worker 处理一个请求」,而是「一个 Worker 内跑多个协程(greenlet),同时处理多个连接」。你多开 10 个 Worker,只是多了 10 个白占内存的进程,并发能力基本没涨。
更糟的是:每个 Worker 会占用一个数据库连接。你从 2 个 Worker 调到 8 个,连接池悄悄多吃了 6 个连接------连接池打到上限的时候,问题才暴露,你还不知道是这个原因。
gevent 到底怎么工作的
同步模式(sync):
ini
Worker 1: [请求A────────────] → 下一个请求
Worker 2: [请求B────────────] → 下一个请求
↑ 一个 Worker 同一时间只干一件事
gevent 模式:
ini
Worker 1: [请求A────] ← 协程1
[请求B────────] ← 协程2
[请求C──] ← 协程3
↑ 一个 Worker 同时处理多个请求,靠协程切换
gevent 的核心能力不是「多开进程」,而是「每个进程多接连接」。
所以调优方向不是增加 Worker,是增加 SERVER_WORKER_CONNECTIONS。
| 参数 | 默认值 | 实际含义 |
|---|---|---|
SERVER_WORKER_AMOUNT |
1 | 进程数。gevent 下 2-4 足够 |
SERVER_WORKER_CONNECTIONS |
10 | 每个进程的最大并发连接数 |
默认 SERVER_WORKER_CONNECTIONS=10。2 个 Worker × 10 连接 = 20 并发。同事开 3 个页面、跑 2 个工作流,连接池就用完了。
这才是真正瓶颈。
怎么配
ini
# docker/.env
# gevent 模式:2-4 个 Worker 就够
# 4 核服务器设 2,8 核设 4
SERVER_WORKER_AMOUNT=2
# 每个 Worker 的并发连接数
# 默认 10 → 建议 50-100
SERVER_WORKER_CONNECTIONS=50
# ⚠️ 数据库连接池必须联动调整(见公式)
SQLALCHEMY_POOL_SIZE=50
💡 还有一个
API_WEBSOCKET_WORKER_CONNECTIONS(默认 1000),它是给 Dify 实时协作功能用的 WebSocket 连接池,和普通 API 的SERVER_WORKER_CONNECTIONS是两个独立参数,别搞混。
联动公式:
SERVER_WORKER_AMOUNT × SERVER_WORKER_CONNECTIONS + CELERY_WORKER_AMOUNT + 10(余量) ≤ SQLALCHEMY_POOL_SIZE + SQLALCHEMY_MAX_OVERFLOW
以上面配置为例:2 × 50 + 4 + 10 = 114,连接池 50 + 10(MAX_OVERFLOW)= 60→ 不够 。要调到 POOL_SIZE=100。
这就是网上教程从来不提醒的联动问题------你改了 Worker 数,数据库连接池不一定够。
还有一层校验: 应用侧的连接池上限不能超过数据库侧。POSTGRES_MAX_CONNECTIONS 默认 200,如果你的 POOL_SIZE + MAX_OVERFLOW 接近或超过这个值,会出现数据库级 too many connections 错误。一般 4C/8C 场景 200 够用,大规模扩容时注意检查。
另外,如果 Dify 部署在反向代理后面,别忘了配这个:
ini
# docker/.env
RESPECT_XFORWARD_HEADERS_ENABLED=true
不配的话,所有请求的客户端 IP 都会显示为代理服务器的地址------日志里全是同一个 IP,出了问题没法排查。
过载保护:被忽略的最后一道防线
还有一个参数大部分人都没配过:
bash
grep APP_MAX_ACTIVE_REQUESTS docker/.env
# 输出 0(或根本没这行)
APP_MAX_ACTIVE_REQUESTS=0 的意思是:并发请求数无上限。
这意味着:就算你 Worker 和连接数都配好了,突然来个流量尖峰,所有连接被占满,新的请求直接挂掉,没有任何排队机制。
ini
# 设一个上限,超出排队等待,不直接崩
APP_MAX_ACTIVE_REQUESTS=30
这个参数不是性能优化------是保险丝。它唯一的作用是:崩的时候体面地排队,而不是直接 502。
Nginx 别忘了
如果你在 Dify 前面挂了 Nginx 做反向代理(大部分生产环境都会),Nginx 的缓存和超时设置会直接影响 Dify 的表现。
最容易翻车的两个点:
1. SSE 流式响应被缓冲
Dify 的工作流输出、Chat 对话都是通过 SSE(Server-Sent Events)流式返回的。Nginx 默认会缓冲响应,导致用户看到的效果是「卡几秒然后突然全部出来」,而不是逐字输出。
ini
location / {
proxy_pass http://127.0.0.1:5001;
proxy_http_version 1.1;
# 关闭缓冲,保证 SSE 流式输出
proxy_buffering off;
proxy_cache off;
# SSE 长连接必须
proxy_set_header Connection '';
}
2. 超时太短
模型推理可能要几十秒甚至几分钟。如果 Nginx 的超时太短,正常的 LLM 调用会被 Nginx 切断。
ini
location / {
# ... 上面那些配置 ...
# LLM 调用可能需要很长时间
proxy_connect_timeout 60s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
}
3. Body 太大
用户上传大文件(PDF、Word 文档做知识库),Nginx 默认 client_max_body_size 只有 1M,入口直接 413。
ini
server {
client_max_body_size 100M;
# ...
}
一个能直接用的 Nginx 配置块
ini
server {
listen 80;
server_name dify.your-domain.com;
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:5001;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection '';
# 关闭缓冲,保证 SSE 流式输出
proxy_buffering off;
proxy_cache off;
# LLM 长耗时调用
proxy_connect_timeout 60s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
}
}
改完 reload:nginx -t && nginx -s reload
快速自查
bash
# 1. Worker 数合理吗?
grep SERVER_WORKER_AMOUNT docker/.env
# gevent 模式 2-4 就够了
# 2. 连接数是真正的瓶颈吗?
grep SERVER_WORKER_CONNECTIONS docker/.env
# 默认 10 → 建议 50-100
# 3. 连接池跟得上吗?
grep SQLALCHEMY_POOL_SIZE docker/.env
# 按公式算:Worker数 × 连接数 + Celery数 + 10 ≤ Pool + Overflow
# 4. 数据库侧连接上限够吗?
grep POSTGRES_MAX_CONNECTIONS docker/.env
# 默认 200,确保 > Pool + Overflow
# 5. 有过载保护吗?
grep APP_MAX_ACTIVE_REQUESTS docker/.env
# 0 = 裸奔,设 30-50
# 6. 反向代理 IP 配置了吗?
grep RESPECT_XFORWARD_HEADERS_ENABLED docker/.env
# 反向代理部署必须设为 true
# 7. Nginx 缓冲关了吗?
grep proxy_buffering /etc/nginx/sites-enabled/dify
# off
接下来
本文是「Dify 并发急救手册」系列第 2 篇。下一篇拆解 Celery 的 15 个队列------为什么 Dify 需要这么多队列、每个队列管什么、不配会怎样。
👉 关注「辉的技术笔记」,获取系列更新
标签: Dify | 后端 | 运维 | Docker | Nginx