一、问题背景
最近在整一个大模型的项目,生产环境用的是一台标准的 8核 16G 云服务器,上面自己独立部署了 Dify 平台。
我们的业务主要已AI对话+工作流为主,没有大文件处理和知识库管理。
- 不玩重活:完全没有大文件解析、数据集批量导入,或者知识库切片这种疯狂吃内存的“重体力活”。
- 全是业务:纯粹的 Workflow 工作流和 Agent 智能体调度,里面塞满了各种大模型(LLM)节点,而且基本全是 Stream 流式输出。
刚上线并发一上来,前端和 API 就频繁蹦出 504 Gateway Timeout。去服务器上一看,16G 内存还剩一大截,但 CPU 各个核心忙得不均匀,Web 请求排大队。
进一步排查发现,Dify 的默认配置(尤其是官方 docker-compose.yml 及 .env 模板)主要面向本地开发或单实例部署优化,部分核心参数过于保守,在高并发或生产级负载下会成为性能瓶颈。
经过一系列参数排查与调优,重点围绕 API 服务层(Gunicorn)与后台任务层(Celery)两组核心配置展开。
二、Dify官方关键参数详解
2.1 API 服务层(Gunicorn)参数
Dify 的 API 服务基于 Gunicorn 作为 WSGI HTTP 服务器。以下三个参数直接决定了 API 的并发处理能力:
| 参数 | 作用 | 默认值 | 说明 |
|---|---|---|---|
SERVER_WORKER_AMOUNT |
Gunicorn 工作进程数 | 1 | 每个进程可独立处理请求,充分利用多核 CPU |
SERVER_WORKER_CLASS |
工作模式 | gevent |
使用协程处理 I/O 密集型并发连接 |
SERVER_WORKER_CONNECTIONS |
每个进程的最大连接数 | 10 | 配合 gevent 模式生效,决定单进程并发通道数 |
注意:Dify API 服务的理论最大并发连接数可近似理解为:
SERVER_WORKER_AMOUNT × SERVER_WORKER_CONNECTIONS
实际并发能力还受数据库连接池、下游 LLM API 延迟等因素制约。
2.2 后台任务层(Celery)参数
知识库文档上传、解析、向量化、索引构建等耗时操作由 Celery 异步任务队列处理。相关核心参数如下:
| 参数 | 作用 | 默认值 |
|---|---|---|
CELERY_WORKER_AMOUNT |
Celery Worker 进程数(并发消费能力) | 1 |
CELERY_AUTO_SCALE |
是否启用自动扩缩容 | false |
CELERY_MAX_WORKERS |
自动扩缩容时的最大 Worker 数 | — |
CELERY_MIN_WORKERS |
自动扩缩容时的最小 Worker 数 | — |
2.3 数据库连接池参数
调高 API 并发后,数据库连接数会成为新的瓶颈,需同步调整:
| 参数 | 作用 | 默认值 |
|---|---|---|
SQLALCHEMY_POOL_SIZE |
SQLAlchemy 连接池大小 | 30 |
SQLALCHEMY_MAX_OVERFLOW |
连接池溢出上限 | 10 |
POSTGRES_MAX_CONNECTIONS |
PostgreSQL 最大连接数 | 100 |
三、配置实践
3.1 问题诊断流程
在调整参数前,建议按以下步骤完成诊断:
-
检查服务器资源基线:
free -h # 查看内存 df -h # 查看磁盘 nproc 或 lscpu # 查看 CPU 核心数 -
确认 Celery 队列积压情况:
redis-cli -h redis -p 6379 llen celery # 查看队列长度 -
检查 Worker 日志:
docker logs -f dify-celery-worker # 观察是否有异常或长时间无日志 -
确认 Worker 存活状态:
celery -A app.celery_worker inspect ping # 检查所有 Worker 心跳
3.2 生产环境8核CPU配置修改
首先是web服务的Gunicorn参数。官方默认使用gevent作为处理方式。
woker推荐并发数:CPU 核心数 × 2 + 1, 保证 8 个物理核心在全并发的时候,每个核心都有至少 2 个进程在疯狂轮询。
每个worker的任务数设置为200,合计可以处理 17 * 200并发量,估计我们系统也没有这么高并发,可以再往下降低,后续看情况调整。
# ============ API 服务层(Gunicorn)============
SERVER_WORKER_AMOUNT=17
# gevent 模式:利用协程处理 I/O 密集型并发
SERVER_WORKER_CLASS=gevent
# 每个 Worker 的最大连接数
SERVER_WORKER_CONNECTIONS=200
别忘了,咱们是纯 Agent/Workflow 场景,绝大多数同步工作流在 Web 进程(SERVER)里直接就跑完了,Celery 顶多接一点零星的异步重试或者后台调度。Celery 进程开多了,反而会跟 SERVER 抢 CPU 资源,光是上下文切换就够系统内耗的了。
所以, Celery 这边我们可以调小一点:
CELERY_WORKER_AMOUNT=4
CELERY_WORKER_CLASS=gevent
CELERY_WORKER_CONCURRENCY=200
3.3、 容易忽视的死穴:数据库 连接池
当全 Gevent 给你提供了几千个潜在并发通道时,底层的数据库(PostgreSQL)立马就成了新的瓶颈。这块要是配不对,Python 端会疯狂报连接池干了,要么数据库直接 down 掉。
# ============ 数据库连接池 ============
# 连接池大小需与 API 并发能力匹配
SQLALCHEMY_POOL_SIZE=200
3.3 配置生效
修改 .env 文件后,需重启相关容器使配置生效:
docker-compose down
docker-compose up -d
若仅需重启 Celery Worker,可执行:
docker-compose restart celery-worker
3.4 验证方法
配置生效后,建议通过以下方式验证:
-
观察队列长度下降:
redis-cli -h redis -p 6379 llen celery确认队列长度持续下降至个位数。
-
检查 Worker 状态:
celery -A app.celery_worker inspect active # 查看当前执行的任务列表 celery -A app.celery_worker inspect stats # 获取 Worker 实时负载 -
在 Dify Web UI 中观察:知识库文件状态是否由“排队中”逐步转为“已完成”。
四、常见问题与排查要点
4.1 后台任务长期卡在“排队中”
现象:上传文档后长期处于 “Processing…” 状态,无法完成。
根因:Celery Worker 并发处理能力不足,任务积压在 Redis 消息队列中,形成“生产快、消费慢”的局面。
解决方案:
- 提升
CELERY_WORKER_AMOUNT - 启用
CELERY_AUTO_SCALE实现动态扩缩容 - 若积压严重且为测试环境,可考虑清空队列(生产环境慎用)
4.2 API 响应慢、聊天卡顿
排查方向:
- 检查
SERVER_WORKER_AMOUNT是否过低 - 确认
SERVER_WORKER_CLASS是否设置为gevent - 检查 CPU、内存资源是否已耗尽
- 确认数据库连接池是否已满(
SQLALCHEMY_POOL_SIZE不足)
4.3 数据库连接数耗尽
现象:高并发下出现数据库连接失败错误。
根因:API 并发提升后,每个 Worker 需要独立的数据库连接,默认连接池大小不足。
解决方案:同步调高 SQLALCHEMY_POOL_SIZE 和 POSTGRES_MAX_CONNECTIONS。
五、总结
Dify 生产环境性能调优的核心在于不同层次的并发调整:
- API 接入层:
SERVER_WORKER_AMOUNT决定并行处理能力,推荐CPU 核心数 × 2 + 1 - 后台任务层:
CELERY_WORKER_AMOUNT决定异步任务吞吐能力,推荐CPU 核心数,配合自动扩缩容 - 数据库连接层:
SQLALCHEMY_POOL_SIZE必须与 API 并发能力匹配,否则上层调优将受制于连接池瓶颈
这台 8核 16G 的机器在跑纯 Workflow/Agent 的时候,吞吐量直接翻了好几倍,再也没卡出过 504 延迟。
