Embedding 服务限流:向量化任务也需要排队纪律

📅 2026/7/6 5:06:13
Embedding 服务限流:向量化任务也需要排队纪律
Embedding 服务限流向量化任务也需要排队纪律一、Embedding 不是便宜到可以无限调用RAG 平台里Embedding 服务经常被当成基础能力。文档导入、增量更新、用户查询、相似推荐都要调用它。因为接口看起来简单团队容易忽略限流。结果是批量导入占满服务在线查询延迟升高甚至把上游模型 API 打到限额。Embedding 服务需要区分在线查询和离线构建。在线查询对延迟敏感批量构建对吞吐敏感。两者共用同一队列就是在让低优先级任务影响用户请求。二、把请求按用途拆成不同通道平台应至少有 query、ingest、rebuild 三类通道。query 用于在线检索前向量化优先级最高ingest 用于普通文档导入rebuild 用于全量重建应该有严格并发上限。flowchart TD A[Embedding 请求] -- B{用途} B --|在线查询| C[Query 通道] B --|文档导入| D[Ingest 队列] B --|索引重建| E[Rebuild 队列] C -- F[短超时模型调用] D -- G[批量合并调用] E -- H[低优先级限速] F -- I[向量返回] G -- J[写入索引] H -- J通道拆开后监控也会更清楚。看到整体 QPS 没意义要知道是哪类请求在消耗额度。三、Go 中间件要按租户和通道同时限流只按全局限流会让大租户影响小租户。只按租户限流又可能让重建任务挤压查询。下面示例展示 key 的设计。type LimitKey struct { TenantID string Channel string } func BuildLimitKey(tenantID, channel string) (string, error) { if tenantID || channel { return , fmt.Errorf(missing limit key field) } switch channel { case query, ingest, rebuild: return tenantID : channel, nil default: return , fmt.Errorf(unknown embedding channel: %s, channel) } }限流失败时在线查询可以快速返回降级结果导入任务则应进入重试队列。不同通道的失败处理不应该一样。四、批量合并要看 Token不只看条数Embedding 批处理常按条数合并但文本长度差异很大。更准确的方式是按 token 预算组批。超过预算的长文本要先切片不能硬塞进同一次请求。还要处理幂等。文档导入可能重复触发同一段文本生成多次向量会浪费成本。可以用文本哈希、模型版本和切片版本作为向量缓存 key。模型升级后再重建不要混用旧向量。最后Embedding 服务要有明确 SLO。在线查询看 P95 延迟导入看积压长度重建看每日完成量。没有指标限流策略就只能靠感觉调。还有一个细节是失败隔离。某个租户导入了异常长文本不能拖慢其他租户的在线查询。队列层要记录拒绝原因并把超长文本标记为待切片而不是让 Worker 一直重试同一条输入。限流不是简单拒绝请求它还要给调用方一个可恢复的下一步。五、总结Embedding 服务要把在线查询、文档导入和索引重建拆成不同通道并按租户与通道同时限流。批处理要按 token 预算合并向量缓存要包含模型和切片版本。向量化看似基础实际上直接影响 RAG 平台的延迟、成本和稳定性。