[Agent开发平台] API网关 | 业务领域 | DTO格式 | 分页令牌
第二章:API网关与处理器
欢迎回到Coze Loop~
在第一章:Cozeloop前端应用中,我们探索了浏览器中的可视化控制面板,了解了前端如何向后端发送请求。
但究竟是谁在接收这些请求?请求如何被处理?
如果把Coze Loop的后端比作繁忙的办公楼,那么前端就是需要办事的客户。这时需要一个清晰的流程来接收请求、引导
至正确部门并返回
结果——这正是API网关与处理器的职责所在。
什么是API网关?
Coze Loop的API网关如同整栋办公楼的接待大厅或安检通道。所有来自前端或其他客户端的请求都必须首先通过这个网关。
为什么需要API网关?
统一入口
:前端无需知晓众多内部服务细节,只需与这个"总服务台"交互
,提升系统可管理性- 初步审查:
- 身份验证:用户是否已登录?
- 权限校验:用户是否有删除提示词等特定操作权限?
- 格式校验:请求是否符合规范格式?
- 日志记录:记录请求方、时间及操作内容
- 流量管控:应对
高并发
请求,防止系统过载 智能路由
:完成审查后,将请求精准分派至对应业务模块
这个组件确保所有外部交互在触及核心业务逻辑前都经过有序化与安全检查。
什么是处理器?
如果说API网关是接待台
,那么处理器就是具体执行请求的专业团队或业务部门。每个处理器专精于处理特定类型的请求。
例如:
- "获取AI智能体列表"请求由
ListModels
处理器处理 - "新建提示词"请求由
CreatePrompt
处理器处理 - "删除数据集"请求由
DeleteDataset
处理器处理
处理器承载着每个API端点的具体业务逻辑,是网络请求与后端核心业务间的直接桥梁
前后端完整通信流程
以第一章的"获取AI智能体列表"为例,完整流程如下:
分步解析:
- 前端请求:点击查看AI智能体时,前端发送HTTP GET请求至后端 [14]
- 网关接收:请求首先到达基于Hertz框架构建的API网关(Hertz是Go语言高性能HTTP框架)
- 中间件处理:
session.SessionMW
:验证用户会话有效性middleware.AccessLogMW
:记录请求明细middleware.PacketAdapterMW
:统一响应格式
- 路由分发:根据URL路径匹配处理器映射表
- 处理器执行:
ListModels
处理器调用LLM管理系统获取数据 - 响应返回:处理器将数据格式化后经网关返回前端
API网关代码
Coze Loop的API网关采用Hertz框架构建,以下是关键代码模块:
1. 网关启动入口(backend/api/api.go
)
// 初始化并启动Hertz服务
func Start(handler *apis.APIHandler)
{// 配置JSON序列化规则render.ResetJSONMarshal(js_conv.GetMarshaler())// 创建服务实例(支持20MB请求体)h := server.Default(server.WithMaxRequestBodySize(20*1024*1024))// 注册所有API路由register(h, handler)// 启动服务监听h.Spin()
}// 初始化处理器组
func Init(ctx context.Context, idgen idgen.IIDGenerator,...) (*apis.APIHandler, error){// 初始化提示词处理器promptHandler := apis.InitPromptHandler(...)// 初始化LLM处理器llmHandler := apis.InitLLMHandler(...)// 返回聚合处理器组return &apis.APIHandler{PromptHandler: promptHandler,LLMHandler: llmHandler,... },nil
}
此模块负责服务配置与处理器组初始化,register()
实现路由注册
2. 处理器组定义(backend/api/handler/coze/loop/apis/handler.go
)
// 聚合所有业务处理器
type APIHandler struct
{*PromptHandler // 提示词管理*LLMHandler // LLM模型管理*DataHandler // 数据管理...
}// LLM处理器结构
type LLMHandler struct
{llmmanage.LLMManageService // 模型管理接口runtime.LLMRuntimeService // 模型运行接口
}
采用模块化设计,每个处理器组对接特定业务领域
3. 路由注册文件(backend/api/router/coze/loop/apis/coze.loop.apis.go
)
func Register(r *server.Hertz, handler *apis.APIHandler)
{apiGroup := r.Group("/api"){llmGroup := apiGroup.Group("/llm"){// 注册模型列表查询路由llmGroup.POST("/v1/models/list", apis.ListModels)// 注册模型详情查询路由llmGroup.POST("/v1/models/:model_id", apis.GetModel)}}
}
此自动生成文件实现URL路径到处理器的精确映射
4. 中间件配置(backend/api/router/coze/loop/apis/middleware.go
)
// 全局中间件
func rootMw() []app.HandlerFunc
{return []app.HandlerFunc{middleware.AccessLogMW(), // 访问日志middleware.LocaleMW(), // 多语言支持}
}// API组中间件
func _apiMw() []app.HandlerFunc
{return []app.HandlerFunc{middleware.SessionMW(...) // 会话验证}
}
分层中间件设计实现安全控制与请求预处理
核心组件对照表
组件 | 类比 | 功能描述 | 技术实现示例 |
---|---|---|---|
API网关 | 总服务台 | 请求入口/流量管控 | Hertz HTTP服务监听端口 |
中间件 | 安检通道 | 身份验证/日志记录 | SessionMW会话中间件 |
路由 | 接待引导员 | URL路径解析与路由分发 | 自动生成的路由注册文件 |
处理器 | 专业业务团队 | 具体业务逻辑执行 | LLMHandler模型管理处理器 |
业务服务 | 后勤支持部门 | 提供数据存取等基础服务 | LLMManageService模型管理服务 |
结语
本章揭示了API网关作为后端"神经中枢"的核心地位,以及处理器作为业务逻辑载体的重要作用
。
这种分层架构设计不仅保障了系统安全性(通过统一入口的鉴权体系 ),还提升了可维护性(模块化处理器设计 )。
下一章我们将深入业务领域应用,解析核心业务逻辑的实现机制。
第三章:业务领域应用
在第二章:API网关与处理器中,我们了解了API网关如何作为后端"接待台"接收前端请求并分派给处理器。
但处理器接收到请求后发生了什么?真正的"重活"由谁完成?
这正是业务领域应用的舞台。
什么是业务领域应用?
将Coze Loop后端比作大型企业,API网关与处理器相当于前台接待与任务分派员,而业务领域应用则是企业内部专注特定业务的专业部门。
例如企业中的"销售部"、“研发部”、“人力资源部”,每个部门专注于特定领域的复杂业务。
在Coze Loop中,这些"部门"是封装核心业务逻辑的软件模块,具有以下特征:
- 功能聚焦:每个应用专注特定业务领域(如提示词调试、LLM管理)
- 业务规则承载:包含完整业务逻辑与验证流程
- 基础设施解耦:通过接口与底层存储/计算资源交互
以"创建新提示词"场景为例:
Coze Loop核心业务领域应用
系统将核心业务划分为六大应用模块:
应用名称 | 职能类比 | 核心职责 | 典型任务场景 |
---|---|---|---|
Prompt | 研发实验室 | 管理提示词全生命周期(创建/调试/版本控制) | 调试复杂提示词模板,执行多版本对比测试 |
LLM | 模型管理中心 | 对接大语言模型服务,管理模型接入与推理 | 部署新LLM服务端点,监控模型推理延迟 |
Evaluation | 质量检测部 | 设计评估方案,分析AI智能体性能 | 构建AB测试环境,生成模型准确率报告 |
Data | 数据资源库 | 管理训练/评估数据集,确保数据版本一致性 | 上传标注数据集,执行数据清洗流水线 |
Foundation | 后勤保障中心 | 提供用户认证、权限管理、文件存储等基础服务 | 配置RBAC权限模型,管理分布式文件存储 |
Observability | 运行监控室 | 收集系统运行指标,提供追踪与诊断能力 | 分析请求链路追踪,监控API网关吞吐量波动 |
请求处理全链路
以"获取AI智能体列表"为例,完整处理流程如下:
关键环节说明:
- 权限校验:应用模块首先通过
Foundation
服务验证用户空间权限 - 数据查询:应用通过
ListModels
方法调用数据库接口 - 数据转换:将
数据库实体
转换为前端所需的DTO格式
- 分页处理:应用维护分页令牌(nextPageToken)实现大数据集分片传输
🎢DTO格式
DTO(Data Transfer Object)格式是一种用于在不同系统或模块间传输数据的结构化对象,通常只包含数据字段
而不含业务逻辑,类似打包好的快递箱,只装数据不处理数据。
DTO的常用编码格式
DTO(Data Transfer Object)通常采用JSON或XML作为主要编码格式,具体选择取决于应用场景和技术栈。
JSON格式
JSON因其轻量级、易读性和广泛支持成为主流选择。大多数现代API(如RESTful服务)默认使用JSON传输DTO数据。示例结构:
{"id": 123,"name": "Example","isActive": true
}
XML格式
XML在传统企业系统或SOAP协议中仍被使用,适合需要严格数据验证的场景。示例结构:
<DTO><id>123</id><name>Example</name><isActive>true</isActive>
</DTO>
Protocol Buffers (protobuf)
在高性能或微服务通信中,二进制格式如protobuf能减少带宽占用。需要预先定义Schema:
message ExampleDTO {int32 id = 1;string name = 2;bool is_active = 3;
}
MessagePack
适用于需要更高效率的二进制JSON替代方案
,保留JSON结构但体积更小
。
选择依据:
- 前后端交互:优先选JSON,因其与JavaScript天然兼容。
- 内部服务通信:考虑protobuf或Avro等二进制协议。
- 遗留系统集成:可能需要XML支持。
注意事项
- 确保字段命名风格一致(如蛇形命名
user_name
或驼峰userName
)。 - 版本兼容性:添加新字段时避免破坏现有解析逻辑。
⭕分页令牌应用方法
服务端
在处理大数据集时生成唯一令牌
(如nextPageToken
),随当前页数据返回客户端
。客户端下次请求携带该令牌,服务端据令牌定位上次断点
继续传输后续数据,直至返回空令牌表示传输完成。
实现逻辑
-
首次请求
客户端发起不带令牌的初始请求,服务端返回第一页数据及nextPageToken
(如page_2
)。 -
后续请求
客户端将收到的nextPageToken
附加到请求参数(如?pageToken=page_2
),服务端解析令牌后返回下一页数据及新令牌。 -
终止条件
当服务端返回空令牌或预定义终止符(如""
或null
),客户端停止请求。
技术要点
- 令牌通常编码分页偏移量(如
游标ID
、时间戳
或加密分页参数
) - 需设计无状态令牌,避免服务端存储会话
- 建议设置令牌有效期,防止旧令牌失效问题
示例流程:
初始请求 -> 返回数据A + token1
请求+token1 -> 返回数据B + token2
请求+token2 -> 返回数据C + (空令牌)
Coze代码实现
1. LLM管理应用(backend/modules/llm/application/manage.go
)
// 说明:处理AI模型列表查询的核心逻辑
func (m *manageApp) ListModels(ctx context.Context, req *manage.ListModelsRequest) (*manage.ListModelsResponse, error)
{// 权限校验(对接Foundation应用)if err := m.auth.CheckSpacePermission(ctx, req.WorkspaceID, "listModels"); err != nil {return nil, errors.New("权限校验失败: "+err.Error()) }// 构建数据库查询条件query := entity.ListModelReq{WorkspaceID: req.WorkspaceID,PageSize: req.PageSize,PageToken: req.PageToken,}// 调用领域服务执行查询models, total, hasMore, nextToken, err := m.manageSrv.ListModels(ctx, query)if err != nil {return nil, errors.New("数据查询异常: "+err.Error())}// 数据格式转换response := &manage.ListModelsResponse{Models: convertToDTO(models),TotalCount: total,HasMore: hasMore,NextPageToken: strconv.FormatInt(nextToken, 10),}return response, nil
}
该代码段展示:
- 权限校验与业务逻辑解耦
- 数据库查询
参数构建
模式 DTO/DO数据转换标准流程
2. 提示词调试应用(backend/modules/prompt/application/debug.go
)
// 说明:处理实时调试流的核心逻辑
func (p *PromptDebugApplicationImpl) DebugStreaming(ctx context.Context, req *debug.DebugStreamingRequest) error
{// 跨应用权限校验if err := p.auth.CheckPromptPermission(req.PromptID); err != nil {return errors.New("提示词调试权限不足")}// 构造调试上下文debugCtx := entity.DebugContext{PromptID: req.PromptID,Parameters: req.Parameters,}// 执行流式调试resultChan := make(chan entity.DebugResult)go p.promptExecutor.StreamingExecute(ctx, debugCtx, resultChan)// 流式响应处理for result := range resultChan {if err := stream.Send(convertToStreamDTO(result)); err != nil {return errors.New("流式传输中断")}}return nil
}
代码亮点:
- 流式处理机制实现
跨应用权限校验
模式上下文隔离
的调试环境构建
流式调试
是通过实时监控
数据流动和中间结果来快速定位
问题,边运行边观察程序状态。
3. 可观测性应用(backend/modules/observability/application/trace.go
)
// 说明:追踪数据查询实现
func (t *TraceApplication) ListSpans(ctx context.Context, req *trace.ListSpansRequest) (*trace.ListSpansResponse, error) {// 请求参数校验if req.WorkspaceID == 0 {return nil, errors.New("workspaceID参数缺失")}// 构建存储层查询query := storage.SpanQuery{TraceID: req.TraceID,StartTime: req.StartTime,PageSize: req.PageSize,PageToken: req.PageToken,}// 调用追踪存储服务spans, nextToken, hasMore, err := t.traceStorage.Query(ctx, query)if err != nil {return nil, errors.New("追踪数据查询失败: "+err.Error())}// 构造分页响应return &trace.ListSpansResponse{Spans: convertSpans(spans),NextPageToken: nextToken,HasMore: hasMore,}, nil
}
该模块展示:
分页
查询标准化实现存储层抽象接口
设计- 追踪
数据转换
逻辑
架构设计
-
模块化隔离
- 每个业务应用独立代码库
- 通过接口定义语言(IDL)明确服务契约
-
依赖倒置原则
-
高层模块(如业务逻辑)不直接依赖低层模块(如具体实现),而是通过抽象(如接口)进行交互,从而降低耦合。
-
图中 LLMApplication 依赖接口 IManageService 和 IAuthProvider,而
非具体实现类
,实现灵活替换和扩展。
-
通过接口依赖实现业务逻辑与基础设施解耦
-
解耦:业务逻辑不受基础设施改动影响。
-
可测试:可通过模拟接口实现单元测试。
-
扩展性:新增实现类无需修改高层代码。
-
-
异常处理规范
- 业务异常分类编码(如
ErrCode=1001
表示权限异常) - 错误信息国际化支持
- 业务异常分类编码(如
-
性能优化
- 批量查询减少数据库IO
- 缓存热点数据
小结
业务领域应用作为Coze Loop的核心业务引擎,承担着以下关键职责:
- 业务规则实施:如权限
校验
、数据校验 - 复杂逻辑封装:如
流式调试
、分页查询 - 基础设施适配:
对接数据库
、缓存等底层服务
这种架构设计带来三大优势:
- 可维护性:
模块边界清晰
,降低代码耦合 - 可扩展性:新业务模块可通过实现
标准接口快速接入
- 可观测性:通过统一指标接口
监控
业务健康度
下一章我们将深入支撑这些业务应用的核心基础设施服务,揭秘数据库、缓存等基础组件的运作机制。
核心基础设施服务