Dify 请求主链路梳理

1. 背景

上一份笔记解决的是"Dify 这个仓库整体由什么组成"。这一份笔记继续回答另一个更关键的问题:

一个请求从哪里发起,经过哪些层,最终落到哪些核心模块?

如果说宏观知识架构解决的是"地图问题",那么请求主链路解决的是"路径问题"。

阅读 Dify 时,真正高频需要掌握的,不是某个类的全部实现细节,而是以下主链路:

  • 前端如何组装请求
  • 请求如何分流到不同 API 前缀
  • Flask 如何注册不同业务入口
  • Controller 如何做鉴权、参数校验、上下文注入
  • Service 如何承接业务
  • 业务何时进入 workflowmodel_runtimerag
  • 何时落 DB、Redis、Celery、向量库

2. 请求主链路总览

先给出最重要的宏观结论:

2.1 Dify 后端不是单入口,而是多入口分流

后端通过蓝图把请求分成几类:

  • /console/api
    • 面向控制台
    • 给已登录的工作台前端使用
    • 典型场景:应用管理、模型配置、知识库管理、工作流编排、工作区设置
  • /api
    • 面向 Web App / 分享页 / 嵌入页
    • 典型场景:聊天、会话列表、消息流式输出、站点访问
  • /v1
    • 面向服务 API / 外部程序集成
    • 典型场景:开发者用 API Key 调用应用、数据集和工作流能力
  • /files
    • 文件相关能力
  • /mcp
    • MCP 相关能力
  • /triggers
    • Trigger / Webhook 能力

也就是说,Dify 的"请求主链路"第一步不是进某个 controller,而是先判断它属于哪条入口线。

2.2 前端同样是多前缀请求

web/config/index.ts 中定义了两个最关键的前端 API 前缀:

  • API_PREFIX
    • 默认指向 http://localhost:5001/console/api
    • 面向控制台请求
  • PUBLIC_API_PREFIX
    • 默认指向 http://localhost:5001/api
    • 面向公开 Web App 请求

因此,前端在发请求时,实际上已经在做第一次业务分流:

  • 控制台请求走 console/api
  • Web App/分享页请求走 api

3. 前端请求是如何发起的

3.1 统一请求封装层

前端核心请求封装在:

  • web/service/fetch.ts
  • web/service/base.ts
  • 各领域 service 文件,如 web/service/apps.ts

其中 fetch.ts 负责的事情很关键:

  • 选择请求基地址
  • 注入 Cookie/CSRF
  • 为公开 Web App 请求注入 X-App-Code
  • 为 Web App 注入 passport / access token
  • 统一处理错误提示
  • 统一处理 204、下载、JSON、流式响应等差异

这意味着:

页面组件通常不直接理解后端细节,而是通过 service 层进入统一请求总线。

3.2 控制台请求链路

web/service/apps.ts 为例:

  • fetchAppList()get(url, { params })
  • createApp()post('apps', { body })
  • fetchAppDetail()get(\{url}/{id}`)`

这些调用默认不带 isPublicAPI,因此最终会走:

  • API_PREFIX
  • 也就是 /console/api

3.3 Web App 请求链路

fetch.ts 中如果 isPublicAPI = true,请求会走:

  • PUBLIC_API_PREFIX
  • /api

同时还会做两件事:

  1. 注入 Authorization
  2. 注入 X-App-CodeX-App-Passport

这说明公开 Web App 的访问不是普通匿名接口,而是带"应用身份 + 终端用户身份"的请求模型。

4. 后端应用初始化与总入口

4.1 Flask app 的创建

后端入口在:

  • api/app_factory.py

这里做了三件关键事情:

  1. 创建 DifyApp
  2. 注册 before_request / after_request
  3. 初始化一组 extensions

其中 before_request 会初始化日志上下文,after_request 会把 OpenTelemetry trace 信息写回响应头。

所以真正的主链路在后端不是"请求直接进 controller",而是:

WSGI/Flask -> app_factory -> before_request -> extensions -> blueprints -> controller

4.2 蓝图注册是后端分流核心

蓝图注册发生在:

  • api/extensions/ext_blueprints.py

这里把几条主入口注册进 Flask:

  • controllers.console -> /console/api
  • controllers.web -> /api
  • controllers.service_api -> /v1
  • controllers.files
  • controllers.inner_api
  • controllers.mcp
  • controllers.trigger

同时,这里还顺手配置了不同入口的 CORS 策略。

所以,阅读 Dify 请求路径时,ext_blueprints.py 是后端的路由分发总图。

5. 三类主请求入口

5.1 Console API

定义位置:

  • api/controllers/console/__init__.py

关键特征:

  • 蓝图前缀:/console/api
  • 面向 Dify 控制台
  • 聚合 app、datasets、workspace、auth、billing、explore 等大量子控制器

这一层的请求通常意味着:

  • 需要控制台登录态
  • 需要租户上下文
  • 需要 workspace / account 权限校验

这是"管理面请求"的主入口。

5.2 Web API

定义位置:

  • api/controllers/web/__init__.py

关键特征:

  • 蓝图前缀:/api
  • 面向最终用户访问的 Web 应用
  • 包含 conversation、message、workflow、login、passport、site 等能力

这一层的重点不是后台管理,而是:

  • 终端用户和具体 App 的关系
  • App Code / Passport 校验
  • 会话、消息、站点访问

这是"运行面请求"的主入口。

5.3 Service API

定义位置:

  • api/controllers/service_api/__init__.py

关键特征:

  • 蓝图前缀:/v1
  • 面向程序化调用
  • 更接近"开放平台 API"

这一层更适合:

  • 外部系统集成
  • 使用 API Key 调用应用
  • 将 Dify 当 BaaS 能力嵌入自有系统

6. Controller 层真正做什么

很多人读到 controller 时容易误判它只是"转发层",但在 Dify 里它承担了几项非常重要的责任。

6.1 参数校验

典型模式是:

  • 用 Pydantic BaseModel 定义 Query/Payload
  • 在请求进入业务逻辑前做结构化校验

例如:

  • 分页参数
  • UUID 参数
  • app mode 参数
  • tracing 参数

这使得请求在非常靠前的位置就被约束住。

6.2 鉴权与上下文注入

例如:

  • api/controllers/console/wraps.py
  • api/controllers/web/wraps.py

两类 wrap 的职责不同:

  • Console wraps
    • 校验 setup、登录态、租户、套餐、权限等
  • Web wraps
    • 解码 Web App passport
    • 校验 X-App-Code
    • 定位 AppSiteEndUser
    • 校验企业版 webapp auth 访问规则

所以 Dify 的 controller 不是"薄 controller"到完全空壳的程度,它在入口层承担了很重的"请求合法化"职责。

6.3 调用 Service 层

当参数和上下文都就绪后,controller 才会进入 service。

这里形成 Dify 很典型的结构:

controller -> service -> core/domain -> repository/model/task

7. Service 层在主链路中的位置

api/services/ 是业务编排主区。它做的不是单纯 CRUD,而是把多个子系统拼起来。

例如一个 service 可能会同时协调:

  • 数据库模型
  • 模型运行时
  • 工作流引擎
  • RAG 检索
  • Celery 异步任务
  • 企业功能开关
  • 插件或工具系统

这意味着:

  • controller 负责"进门"
  • service 负责"把事办成"
  • core 负责"真正执行核心 AI 能力"

8. 核心能力层如何接入请求链路

8.1 工作流链路

当请求触发工作流应用、调试工作流、运行节点、查看执行状态时,通常会继续下钻到:

  • api/core/workflow/

这里的关键对象包括:

  • Graph
  • Node
  • Edge
  • Runtime State
  • Event
  • Layer
  • Command Channel

真正复杂的 AI 编排逻辑,大多在这一层,而不在 controller 或 service 表层。

8.2 模型运行时链路

当请求涉及模型选择、模型调用、参数配置、Provider 凭证时,会继续进入:

  • api/core/model_runtime/

这一层负责:

  • 统一不同模型供应商
  • 统一不同模型能力类型
  • 统一参数规则和鉴权方式

这也是为什么前端无需针对每个模型供应商改一套页面逻辑。

8.3 RAG 链路

当请求涉及数据集、文档导入、切片、召回、重排时,会进入:

  • api/core/rag/
  • api/services/rag_pipeline/
  • api/services/document_indexing_proxy/

此时请求主链路通常不再是一个同步数据库 CRUD,而会扩展为:

HTTP 请求 -> service -> 文档处理/索引任务 -> 向量化/入库 -> 检索配置生效

9. 异步任务与中间件如何介入主链路

很多 Dify 请求不是"一次 HTTP 完成所有工作",而是"HTTP 触发 + 异步处理继续执行"。

常见介入点包括:

  • PostgreSQL
    • 存主业务数据
  • Redis
    • 缓存、队列协同、状态协调
  • Celery
    • 文档处理、异步工作流、清理任务等
  • Vector DB
    • 知识库索引与检索

因此,Dify 的真实请求主链路往往是:

Browser -> Web -> API -> Service -> DB/Redis/Core -> Celery/VectorDB -> 回写状态 -> 前端轮询或流式消费

而不是普通 SaaS 那种:

Browser -> API -> DB -> Response

10. 样例 1:控制台"应用管理"请求链路

这里用"获取/创建应用"作为控制台主链路样例。

10.1 前端发起

文件:

  • web/service/apps.ts

典型调用:

  • fetchAppList()
  • createApp()

它们最终通过统一 get/post 方法走到 API_PREFIX,也就是:

  • /console/api

10.2 后端路由入口

文件:

  • api/controllers/console/__init__.py
  • api/controllers/console/app/app.py

console 蓝图统一挂在 /console/api 下,app.py 提供 app 相关资源接口。

10.3 控制器处理

api/controllers/console/app/app.py 中可以看到几类典型动作:

  • 定义 Query/Payload 模型
  • 校验 app mode、分页参数、tag ids 等
  • 做登录/初始化/套餐/权限装饰器校验
  • 调用 AppService

10.4 Service 承接业务

文件:

  • api/services/app_service.py

这里能看到 Dify 不是简单插一条 app 记录,而是会继续做:

  • 根据 app mode 选择默认模板
  • 通过 ModelManager 解析默认模型
  • 初始化 AppModelConfig
  • 写数据库
  • 发出 app_was_created 事件
  • 根据 feature 开关更新 webapp access mode
  • 清理 billing cache

这正是 Dify 请求主链路的典型风格:

一个看起来简单的接口,背后会联动多个平台子系统。

11. 样例 2:Web App"会话列表"请求链路

这里用公开 Web App 的会话列表作为第二个样例。

11.1 前端发起

公开 Web App 请求会设置:

  • isPublicAPI: true

这样统一请求层会走:

  • PUBLIC_API_PREFIX
  • /api

同时自动加上:

  • Authorization
  • X-App-Code
  • X-App-Passport

11.2 后端路由入口

文件:

  • api/controllers/web/__init__.py
  • api/controllers/web/conversation.py

这里的资源路径是:

  • /api/conversations

11.3 Web wraps 注入上下文

文件:

  • api/controllers/web/wraps.py

WebApiResource 会通过装饰器自动执行:

  • 解析请求头里的 app code
  • 提取并校验 passport
  • 找到 App
  • 找到 Site
  • 找到 EndUser
  • 校验企业版 Web App 权限模式

所以 controller 方法签名里可以直接拿到:

  • app_model
  • end_user

这是 Dify Web 侧请求设计里非常关键的一层抽象。

11.4 控制器处理

文件:

  • api/controllers/web/conversation.py

它会:

  • 校验 app 是否是 chat / agent-chat / advanced-chat
  • 校验分页参数
  • 调用 WebConversationService.pagination_by_last_id(...)
  • 返回结构化分页结果

11.5 Service 与数据库

这一链路下,service 会结合:

  • app_model
  • end_user
  • InvokeFrom.WEB_APP

去读取该终端用户在该 app 下的会话数据,再返回给前端。

这说明 Dify 的公开 Web 请求不是单纯"按用户 token 查数据",而是同时绑定:

  • app 身份
  • 站点身份
  • 终端用户身份
  • 访问来源

12. 从主链路理解 Dify 的设计特点

把上述链路压缩后,可以看到 Dify 有几个非常鲜明的设计特征。

12.1 入口分层清晰

  • Console API 处理管理面
  • Web API 处理运行面
  • Service API 处理对外程序集成

这让不同访问者不会混进同一套路由语义里。

12.2 Controller 负责入口合法化

controller 不只是收参,它还做:

  • 参数结构化
  • 鉴权
  • 上下文定位
  • feature gating
  • edition / billing / permission 校验

12.3 Service 负责跨子系统编排

service 往往要同时操作:

  • 数据模型
  • 配置模型
  • 模型运行时
  • 工作流
  • RAG
  • 插件
  • 异步任务

12.4 Core 负责真正的 AI 执行能力

真正的护城河不在 HTTP 层,而在:

  • core/workflow
  • core/model_runtime
  • core/rag

13. 建议的源码阅读顺序

如果是为了"看懂 Dify 请求怎么走",建议按这个顺序读:

  1. web/config/index.ts
  2. web/service/fetch.ts
  3. web/service/base.ts
  4. api/app_factory.py
  5. api/extensions/ext_blueprints.py
  6. api/controllers/console/__init__.py
  7. api/controllers/web/__init__.py
  8. api/controllers/service_api/__init__.py
  9. api/controllers/console/wraps.py
  10. api/controllers/web/wraps.py
  11. 任选一个垂直样例继续下钻:
    • api/controllers/console/app/app.py -> api/services/app_service.py
    • api/controllers/web/conversation.py -> api/services/web_conversation_service.py

14. 总结

Dify 的请求主链路可以概括成一句话:

前端统一请求封装做第一次分流,Flask 蓝图做第二次分流,controller 完成入口合法化,service 编排业务,core 执行 AI 能力,最终由 DB/Redis/Celery/VectorDB 等基础设施共同支撑。

如果把这个链路真正看清,后面再读任何模块都会轻松很多,因为你会知道它处在整条链的哪个位置:

  • 在入口层
  • 在业务编排层
  • 在核心 AI 执行层
  • 在异步/存储支撑层
相关推荐
Thomas.Sir2 小时前
第十二章:Prompt 提示工程 之 实战项目
python·prompt
2601_950760792 小时前
IFN-γ蛋白在肿瘤免疫中的双重作用机制研究
人工智能
Yao.Li2 小时前
PLY 模型、分割图、RGB 图、深度图之间的关系与坐标系变换详解
人工智能·数码相机·计算机视觉
乱世刀疤2 小时前
ubuntu24上安装openclaw后配置钉钉通道
人工智能·openclaw
gaozhiyong08132 小时前
2026年DeepSeek-V4官网VS Gemini 3.1 pro 官网硬核技术拆解:开源模型的性价比革命
人工智能
第一程序员2 小时前
Python自动化办公:提升工作效率的利器
python·github
冬至喵喵2 小时前
Agent Harness: 一套让 AI Agent 能够驾驭和控制 GUI 软件的适配层
人工智能
踩着两条虫2 小时前
AI驱动的 Vue3应用开发平台深入探究(十五):扩展与定制之自定义设置器与属性编辑器
前端·vue.js·人工智能·低代码·系统架构·编辑器
Surmon8 小时前
彻底搞懂大模型 Temperature、Top-p、Top-k 的区别!
前端·人工智能