[Agent开发平台] API网关 | 业务领域 | DTO格式 | 分页令牌

第二章:API网关与处理器

欢迎回到Coze Loop~

第一章:Cozeloop前端应用中,我们探索了浏览器中的可视化控制面板,了解了前端如何向后端发送请求。

但究竟是谁在接收这些请求?请求如何被处理?

如果把Coze Loop的后端比作繁忙的办公楼,那么前端就是需要办事的客户。这时需要一个清晰的流程来接收请求、引导至正确部门并返回结果------这正是API网关处理器的职责所在。

什么是API网关?

Coze Loop的API网关 如同整栋办公楼的接待大厅安检通道。所有来自前端或其他客户端的请求都必须首先通过这个网关。

为什么需要API网关?

  • 统一入口 :前端无需知晓众多内部服务细节,只需与这个"总服务台"交互,提升系统可管理性
  • 初步审查
    • 身份验证:用户是否已登录?
    • 权限校验:用户是否有删除提示词等特定操作权限?
    • 格式校验:请求是否符合规范格式?
    • 日志记录:记录请求方、时间及操作内容
  • 流量管控 :应对高并发请求,防止系统过载
  • 智能路由:完成审查后,将请求精准分派至对应业务模块

这个组件确保所有外部交互在触及核心业务逻辑前都经过有序化与安全检查。

什么是处理器?

如果说API网关是接待台,那么处理器 就是具体执行请求的专业团队业务部门。每个处理器专精于处理特定类型的请求。

例如:

  • "获取AI智能体列表"请求由ListModels处理器处理
  • "新建提示词"请求由CreatePrompt处理器处理
  • "删除数据集"请求由DeleteDataset处理器处理

处理器承载着每个API端点的具体业务逻辑,是网络请求与后端核心业务间的直接桥梁

前后端完整通信流程

以第一章的"获取AI智能体列表"为例,完整流程如下:

分步解析

  1. 前端请求:点击查看AI智能体时,前端发送HTTP GET请求至后端 [14]
  2. 网关接收:请求首先到达基于Hertz框架构建的API网关(Hertz是Go语言高性能HTTP框架)
  3. 中间件处理
    • session.SessionMW:验证用户会话有效性
    • middleware.AccessLogMW:记录请求明细
    • middleware.PacketAdapterMW:统一响应格式
  4. 路由分发 :根据URL路径匹配处理器映射表
  5. 处理器执行ListModels处理器调用LLM管理系统获取数据
  6. 响应返回:处理器将数据格式化后经网关返回前端

API网关代码

Coze Loop的API网关采用Hertz框架构建,以下是关键代码模块:

1. 网关启动入口(backend/api/api.go)
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)
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)
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)
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智能体列表"为例,完整处理流程如下:

关键环节说明

  1. 权限校验 :应用模块首先通过Foundation服务验证用户空间权限
  2. 数据查询 :应用通过ListModels方法调用数据库接口
  3. 数据转换 :将数据库实体转换为前端所需的DTO格式
  4. 分页处理:应用维护分页令牌(nextPageToken)实现大数据集分片传输

🎢DTO格式

DTO(Data Transfer Object)格式是一种用于在不同系统或模块间传输数据的结构化对象,通常只包含数据字段而不含业务逻辑,类似打包好的快递箱,只装数据不处理数据。

DTO的常用编码格式

DTO(Data Transfer Object)通常采用JSON或XML作为主要编码格式,具体选择取决于应用场景和技术栈。

JSON格式

JSON因其轻量级、易读性和广泛支持成为主流选择。大多数现代API(如RESTful服务)默认使用JSON传输DTO数据。示例结构:

json 复制代码
{
  "id": 123,
  "name": "Example",
  "isActive": true
}

XML格式

XML在传统企业系统或SOAP协议中仍被使用,适合需要严格数据验证的场景。示例结构:

xml 复制代码
<DTO>
  <id>123</id>
  <name>Example</name>
  <isActive>true</isActive>
</DTO>

Protocol Buffers (protobuf)

在高性能或微服务通信中,二进制格式如protobuf能减少带宽占用。需要预先定义Schema:

protobuf 复制代码
message ExampleDTO {
  int32 id = 1;
  string name = 2;
  bool is_active = 3;
}

MessagePack

适用于需要更高效率的二进制JSON替代方案,保留JSON结构但体积更小

选择依据:

  • 前后端交互:优先选JSON,因其与JavaScript天然兼容。
  • 内部服务通信:考虑protobuf或Avro等二进制协议。
  • 遗留系统集成:可能需要XML支持。

注意事项

  • 确保字段命名风格一致(如蛇形命名user_name或驼峰userName)。
  • 版本兼容性:添加新字段时避免破坏现有解析逻辑。

⭕分页令牌应用方法

服务端在处理大数据集时生成唯一令牌(如nextPageToken),随当前页数据返回客户端。客户端下次请求携带该令牌,服务端据令牌定位上次断点继续传输后续数据,直至返回空令牌表示传输完成。

实现逻辑
  1. 首次请求

    客户端发起不带令牌的初始请求,服务端返回第一页数据及nextPageToken(如page_2)。

  2. 后续请求

    客户端将收到的nextPageToken附加到请求参数(如?pageToken=page_2),服务端解析令牌后返回下一页数据及新令牌。

  3. 终止条件

    当服务端返回空令牌或预定义终止符(如""null),客户端停止请求。

技术要点
  • 令牌通常编码分页偏移量(如游标ID时间戳加密分页参数
  • 需设计无状态令牌,避免服务端存储会话
  • 建议设置令牌有效期,防止旧令牌失效问题

示例流程:

css 复制代码
初始请求 -> 返回数据A + token1
请求+token1 -> 返回数据B + token2
请求+token2 -> 返回数据C + (空令牌) 

Coze代码实现

1. LLM管理应用(backend/modules/llm/application/manage.go)
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)
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)
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
}

该模块展示:

  • 分页查询标准化实现
  • 存储层抽象接口设计
  • 追踪数据转换逻辑

架构设计

  1. 模块化隔离

    • 每个业务应用独立代码库
    • 通过接口定义语言(IDL)明确服务契约
  2. 依赖倒置原则

    • 高层模块(如业务逻辑)不直接依赖低层模块(如具体实现),而是通过抽象(如接口)进行交互,从而降低耦合。

    • 图中 LLMApplication 依赖接口 IManageService 和 IAuthProvider,而非具体实现类,实现灵活替换和扩展。

    • 通过接口依赖实现业务逻辑与基础设施解耦

    • 解耦:业务逻辑不受基础设施改动影响。

    • 可测试:可通过模拟接口实现单元测试。

    • 扩展性:新增实现类无需修改高层代码。

  3. 异常处理规范

    • 业务异常分类编码(如ErrCode=1001表示权限异常)
    • 错误信息国际化支持
  4. 性能优化

    • 批量查询减少数据库IO
    • 缓存热点数据

小结

业务领域应用作为Coze Loop的核心业务引擎,承担着以下关键职责:

  • 业务规则实施 :如权限校验、数据校验
  • 复杂逻辑封装 :如流式调试、分页查询
  • 基础设施适配对接数据库、缓存等底层服务

这种架构设计带来三大优势:

  1. 可维护性模块边界清晰,降低代码耦合
  2. 可扩展性 :新业务模块可通过实现标准接口快速接入
  3. 可观测性 :通过统一指标接口监控业务健康度

下一章我们将深入支撑这些业务应用的核心基础设施服务,揭秘数据库、缓存等基础组件的运作机制。

核心基础设施服务

相关推荐
七月shi人17 分钟前
【AI编程工具IDE/CLI/插件专栏】- 热门AI编程CLI初识与IDE对比
ide·人工智能·ai·ai编程
wow_DG43 分钟前
【Pytorch✨】LSTM01 入门
人工智能·pytorch·lstm
apocelipes1 小时前
atomic不是免费午餐
java·性能优化·golang·并发
不会计算机的g_c__b1 小时前
搜索引擎评估革命:用户行为模型如何颠覆传统指标?
人工智能·自然语言处理·机器翻译
萑澈1 小时前
大语言模型提示词工程详尽实战指南
人工智能·语言模型·自然语言处理
Blossom.1182 小时前
基于深度学习的医学图像分析:使用DeepLabv3+实现医学图像分割
人工智能·python·深度学习·yolo·目标检测·机器学习·迁移学习
808&Heartbreak*2 小时前
CNN实战项目
人工智能·神经网络·cnn
大公产经晚间消息2 小时前
网易云音乐硬刚腾讯系!起诉SM娱乐滥用市场支配地位
大数据·人工智能·娱乐
李子圆圆2 小时前
电力设施通道防外破防异物实时监控预警装置的核心功能是什么
人工智能·语音识别