首页
/ Dify VS Code 调试实战:launch.json.template 调试配置全解析与 gevent/Celery 断点原理

Dify VS Code 调试实战:launch.json.template 调试配置全解析与 gevent/Celery 断点原理

2026-09-05 10:12:26作者:尤峻淳Whitney

本篇基于 .vscode/README.md 与配套模板 .vscode/launch.json.template 展开,讲解如何在 VS Code / Cursor 中为 Dify 搭建 API(gevent 服务)与 Celery Worker 两套本地调试环境,并结合 api/app.pydev/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 格式化器、保存时自动修复等),与调试无直接关系,可参考后自行启用。

此外仓库中还有两个子项目级调试文件,可作为对照参考:

使用方法:四步启用模板

README 给出的操作流程非常直接,核心思想是:模板文件只是模板,VS Code 只会识别 .vscode/launch.json,因此需要你手动“转正”它

  1. 创建 launch.json:若 .vscode 目录下尚不存在 launch.json,先创建该文件(例如从 VS Code 运行与调试面板新建,或手工创建空文件);
  2. 复制内容:将 .vscode/launch.json.template全部内容复制进新建的 launch.json(注意是整份覆盖/粘贴,保留 "version": "0.2.0"configurations 结构);
  3. 打开运行与调试视图:在 VS Code / Cursor 中按 Ctrl+Shift+D(macOS 为 Cmd+Shift+D)进入 Run and Debug 面板;
  4. 选择配置并启动:在顶部下拉菜单中选择 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 appgevent.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.pypywsgi.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-workerCOMMUNITY 版本默认的 QUEUES 完全一致(datasetdataset_summarypriority_datasetpriority_pipelinepipelinemailops_traceapp_deletionpluginworkflow_storageconversationworkflowschedule_pollerschedule_executortriggered_workflow_dispatchertrigger_refresh_executorretentionworkflow_based_app_execution),意味着用这份配置调试 worker 时,文档索引、工作流执行、邮件、插件操作等所有社区版任务都能被消费,便于端到端复现问题。
  • justMyCode: false:与 API 配置相反,worker 调试特意关闭“仅限我的代码”,因为任务执行问题往往需要单步进入 Celery 框架、SQLAlchemy 等第三方代码才能定位,放开第三方栈能大幅减少排查盲区。
  • env: {}:模板预留的空环境对象,方便按需注入 REDIS_URLDB_USERNAME 等调试专用变量,而不必改动 .env

调试 worker 前需要的前置条件

dev/start-worker 脚本揭示了 worker 的常规启动方式(uv run celery -A app.celery worker ...,见 dev/start-worker);换成 IDE 调试前请确保:

  1. api/.venv 虚拟环境已创建且依赖齐全(模板硬编码了 api/.venv/bin/python,若你的环境路径不同需相应修改 python 字段);
  2. api/.env 已配置好 PostgreSQL 与 Redis 连接,worker 启动时 app.celery 的构建过程会读取这些配置;
  3. Redis 中对应的队列可被投递任务——例如在 Dify 控制台上传文档、触发工作流,即可让 worker 命中断点。

对照参考:api/.vscode/launch.json.example 的另一种玩法

如果选择把 VS Code 的工作区直接开在 api/ 目录,可参考 api/.vscode/launch.json.example,它展示了与根模板不同的调试策略:

  • API 项:使用 program: app.py + envFile: .env 显式加载环境变量,并注入 FLASK_DEBUG=1GEVENT_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_summarypriority_datasetretentionworkflow_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.oxcsource.fixAll.eslint 自动修复;
  • Cucumber 插件指向 e2e/features/**/*.featuree2e/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 切换浏览器。
登录后查看全文
热门项目推荐
相关项目推荐