Dify VS Code 调试实战:launch.json.template 调试配置全解析与 gevent/Celery 断点原理
本篇基于 .vscode/README.md 与配套模板 .vscode/launch.json.template 展开,讲解如何在 VS Code / Cursor 中为 Dify 搭建 API(gevent 服务)与 Celery Worker 两套本地调试环境,并结合 api/app.py 与 dev/start-worker 源码,说明每个调试参数(gevent.monkey 模块启动方式、gevent: true、队列清单等)背后的运行原理。读完后你可以直接复制模板完成配置,理解 gevent 协程环境下的断点行为,并能按需为前端添加 Chrome/Edge 调试项。
目录中的调试相关文件
仓库 .vscode 目录共提供三个文件,各司其职:
- .vscode/README.md:调试配置的官方使用说明(本文主体文档);
- .vscode/launch.json.template:可直接复制到
launch.json的调试配置模板,内含两个配置项:Python: API (gevent)与Python: Celery Worker (Solo); - .vscode/settings.example.json:编辑器设置示例(oxc 格式化器、保存时自动修复等),与调试无直接关系,可参考后自行启用。
此外仓库中还有两个子项目级调试文件,可作为对照参考:
- api/.vscode/launch.json.example:以
api目录为工作区的示例,使用 gevent 池并附带 compounds 组合启动; - web/.vscode/launch.json:前端示例,仅包含一条指向
http://localhost:3000的 Chrome 启动配置。
使用方法:四步启用模板
README 给出的操作流程非常直接,核心思想是:模板文件只是模板,VS Code 只会识别 .vscode/launch.json,因此需要你手动“转正”它。
- 创建
launch.json:若.vscode目录下尚不存在launch.json,先创建该文件(例如从 VS Code 运行与调试面板新建,或手工创建空文件); - 复制内容:将 .vscode/launch.json.template 的全部内容复制进新建的
launch.json(注意是整份覆盖/粘贴,保留"version": "0.2.0"与configurations结构); - 打开运行与调试视图:在 VS Code / Cursor 中按
Ctrl+Shift+D(macOS 为Cmd+Shift+D)进入 Run and Debug 面板; - 选择配置并启动:在顶部下拉菜单中选择
Python: API (gevent)或Python: Celery Worker (Solo),点击绿色播放按钮即可在断点处进入调试。
由于模板文件名为
launch.json.template而非launch.json,VS Code 不会自动加载它——这正是 README 要求手动复制的原因,也避免了开发者本地个性化配置被模板覆盖。
配置一:Python: API (gevent) —— 调试 gevent 化 API 服务
模板中第一个配置完整内容如下:
{
"name": "Python: API (gevent)",
"type": "debugpy",
"request": "launch",
"module": "gevent.monkey",
"args": ["--module", "app"],
"gevent": true,
"jinja": true,
"justMyCode": true,
"cwd": "${workspaceFolder}/api",
"python": "${workspaceFolder}/api/.venv/bin/python"
}
参数逐项解析
| 字段 | 取值 | 作用 |
|---|---|---|
type / request |
debugpy / launch |
以 Python 调试器启动新进程(非附加到已有进程) |
module + args |
gevent.monkey + ["--module", "app"] |
等价于在 api/ 目录下执行 python -m gevent.monkey --module app:先完成 gevent monkey 补丁,再运行 app 模块 |
gevent |
true |
开启 debugpy 的 gevent 感知模式,让断点能在 greenlet(协程)之间正确切换与暂停 |
jinja |
true |
启用 Jinja2 模板断点,可直接对 HTML 模板行打断点 |
justMyCode |
true |
只在自己代码中暂停,不深入第三方库 |
cwd |
${workspaceFolder}/api |
工作目录指向 API 后端,保证 .env、模块导入路径正确 |
python |
api/.venv/bin/python |
固定使用 api 子目录下的 uv 虚拟环境解释器 |
为什么必须经过 gevent.monkey 启动
这是本配置最关键的一处,源码在 api/app.py 中有完整注释:
# ``python -m app`` (docker DEBUG=true, or IDE debugging) serves through the
# gevent pywsgi server at the bottom of this file, so the stdlib must be
# monkey-patched BEFORE any other import pulls in sockets or locks.
即:当以 python -m app 方式启动时(docker DEBUG=true 或 IDE 调试),Dify API 跑在 gevent pywsgi 服务器上;如果标准库的 socket/锁没有被提前 monkey-patch,每个请求都会变成“单线程上跑一个阻塞 greenlet”——一次 LLM 调用、Future.result 等待或数据库 I/O 就会把整个进程卡死,直到调用返回。因此调试配置的启动方式刻意设计成 python -m gevent.monkey --module app:gevent.monkey 模块自带“先打补丁、再委托运行另一模块”的能力,确保补丁先于一切 socket 导入生效。
app.py 内部还有一层自保护(api/app.py):仅当 __name__ == "__main__" 时才执行 monkey.patch_all(),并额外补丁 psycogreen.gevent(PostgreSQL 驱动)与 grpc.experimental.gevent(gRPC)。生产路径则由 Gunicorn(gunicorn.conf.py 指定 gevent worker)与 Celery(celery_entrypoint.py)各自完成补丁,调试路径与生产路径的补丁时机一致,保证了“调试时看到的行为即生产行为”。
启动后,进程会在 0.0.0.0:5001 上以 gevent WebSocket 服务形式监听(见 api/app.py 的 pywsgi.WSGIServer + WebSocketHandler),这与 docker DEBUG=true 模式的服务形态相同,因此 API 调试期间可以直接用前端或 curl 打真实流量触发断点。
配置二:Python: Celery Worker (Solo) —— 调试异步任务
第二个配置完整内容:
{
"name": "Python: Celery Worker (Solo)",
"type": "debugpy",
"request": "launch",
"module": "celery",
"env": {},
"args": [
"-A", "app.celery", "worker",
"-P", "solo",
"-c", "1",
"-Q", "dataset,dataset_summary,priority_dataset,priority_pipeline,pipeline,mail,ops_trace,app_deletion,plugin,workflow_storage,conversation,workflow,schedule_poller,schedule_executor,triggered_workflow_dispatcher,trigger_refresh_executor,retention,workflow_based_app_execution",
"--loglevel", "INFO"
],
"justMyCode": false,
"cwd": "${workspaceFolder}/api",
"python": "${workspaceFolder}/api/.venv/bin/python"
}
关键参数解读
-A app.celery:指定 Celery 应用实例。app.celery属性在api/app.py中由create_app()生成后挂在app.extensions["celery"]上(见 api/app.py),即调试 worker 启动时同样会完整构建 Flask 应用,与 API 侧共享同一套配置与环境读取逻辑。-P solo -c 1:使用 solo 事件池、并发 1。调试场景下刻意不使用 gevent/prefork 池——单进程单任务意味着任意时刻最多只有一条任务在跑,断点不会被并发任务“抢跑”,行为最可预测;这也解释了配置名中的 “(Solo)”。-Q <18 条队列>:一次性订阅 Dify 社区版的全部任务队列。该清单与启动脚本 dev/start-worker 中COMMUNITY版本默认的QUEUES完全一致(dataset、dataset_summary、priority_dataset、priority_pipeline、pipeline、mail、ops_trace、app_deletion、plugin、workflow_storage、conversation、workflow、schedule_poller、schedule_executor、triggered_workflow_dispatcher、trigger_refresh_executor、retention、workflow_based_app_execution),意味着用这份配置调试 worker 时,文档索引、工作流执行、邮件、插件操作等所有社区版任务都能被消费,便于端到端复现问题。justMyCode: false:与 API 配置相反,worker 调试特意关闭“仅限我的代码”,因为任务执行问题往往需要单步进入 Celery 框架、SQLAlchemy 等第三方代码才能定位,放开第三方栈能大幅减少排查盲区。env: {}:模板预留的空环境对象,方便按需注入REDIS_URL、DB_USERNAME等调试专用变量,而不必改动.env。
调试 worker 前需要的前置条件
dev/start-worker 脚本揭示了 worker 的常规启动方式(uv run celery -A app.celery worker ...,见 dev/start-worker);换成 IDE 调试前请确保:
api/.venv虚拟环境已创建且依赖齐全(模板硬编码了api/.venv/bin/python,若你的环境路径不同需相应修改python字段);api/.env已配置好 PostgreSQL 与 Redis 连接,worker 启动时app.celery的构建过程会读取这些配置;- Redis 中对应的队列可被投递任务——例如在 Dify 控制台上传文档、触发工作流,即可让 worker 命中断点。
对照参考:api/.vscode/launch.json.example 的另一种玩法
如果选择把 VS Code 的工作区直接开在 api/ 目录,可参考 api/.vscode/launch.json.example,它展示了与根模板不同的调试策略:
- API 项:使用
program: app.py+envFile: .env显式加载环境变量,并注入FLASK_DEBUG=1、GEVENT_SUPPORT=True; - Celery 项:改用
-P gevent -c 1的 gevent 池(而非 solo),--loglevel DEBUG拉高日志级别,队列清单为 14 条(dataset,priority_pipeline,pipeline,mail,ops_trace,app_deletion,plugin,workflow_storage,conversation,workflow,workflow_based_app_execution,schedule_poller,schedule_executor,triggered_workflow_dispatcher,trigger_refresh_executor),比根模板少了dataset_summary、priority_dataset、retention、workflow_based_app_execution等较新增量队列,可见两份文件面向的队列代际略有差异; - compounds 组合:定义了
"Launch Flask and Celery"复合配置,一次点击同时拉起 API 与 Celery 两个调试进程,适合需要前后端(API + 任务)联动的断点场景。根模板未包含 compounds,如需可参照该示例自行补充。
前端调试与 Edge 浏览器提示
README 的 Tips 部分还给出了一条针对前端的经验:如果你希望用 Microsoft Edge 而不是 Chrome 调试前端,应修改 “Next.js: debug full stack” 配置段中的 serverReadyAction,把 "debugWithChrome" 改为 "debugWithEdge"。
需要说明的是:从仓库现状看,web/.vscode/launch.json 目前只包含一条基础的 "Launch Chrome against localhost"(url 指向 http://localhost:3000)配置,而 “Next.js: debug full stack” 这一完整配置并不在仓库模板内——该提示面向的是开发者基于 Next.js 工具链(如 Create Next App 生成的 full-stack 调试配置)自行补全后的 launch.json。也就是说,当你为自己的 launch.json 增加了 Next.js 全栈调试段后,只需这一处字符串改动即可切换调试浏览器。
配套的编辑器设置建议
虽然不是调试本身的一部分,.vscode/settings.example.json 值得在调试期间一并启用,它约定了:
- 前端各语言(JS/TS/TSX/JSON/YAML/CSS 等)统一使用
oxc.oxc-vscode作为默认格式化器,并开启editor.formatOnSave; - ESLint 使用 flat config,保存时显式触发
source.fixAll.oxc与source.fixAll.eslint自动修复; - Cucumber 插件指向
e2e/features/**/*.feature与e2e/features/**/*.ts,方便对 e2e 用例做编辑体验增强; - Tailwind 实验性配置指向
web/app/styles/globals.css。
将示例内容复制到 .vscode/settings.json 后,代码风格修复会在保存时自动完成,减少调试循环中因格式问题产生的干扰。
小结与实操建议
- 根目录调试选 .vscode/launch.json.template 复制为
launch.json,API 用 gevent 池形态、worker 用 solo 池形态,两条链路都经过 debugpy 的 gevent 感知机制,断点行为与 api/app.py 注释描述的运行时模型一致; - 队列订阅范围与 dev/start-worker 的社区版默认队列对齐,调试 worker 时能覆盖文档处理、工作流执行、调度等全部社区版任务;
- 需要 API + 任务联动断点时,可参照 api/.vscode/launch.json.example 增加 compounds 组合启动;
- 前端侧从 web/.vscode/launch.json 的 Chrome 基础配置出发,按需扩展为 Next.js full-stack 调试段,并可用 README 提示的
debugWithEdge切换浏览器。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00