AI应用从请求链路到异步任务与多Region完整架构
生产 AI 应用不是 Controller 里调用一次模型 API。它是由身份、租户、场景路由、Prompt、Memory、RAG、Tool、模型网关、输出校验、评估、成本和审计组成的分布式执行链。模型只是其中一个不确定组件,数据库、权限和业务工具才是事实与执行权威。
本页从一条请求开始,解释同步、SSE流式和异步任务怎样运行,模型网关怎样路由和限流,长任务怎样用租约、Checkpoint、Outbox和幂等恢复,以及多Region和生产故障怎样治理。
学习目标
完成本页后,你应该能够:
- 解释入口、编排、知识、工具、模型和治理层的职责边界。
- 画出一次AI请求从浏览器到模型再返回的完整链路。
- 区分场景路由与模型路由。
- 设计模型网关的Provider适配、Deadline、重试、配额和版本记录。
- 根据任务选择同步、SSE流式或异步模式。
- 解释SSE断连、取消传播和网关缓冲。
- 设计异步任务状态机、Worker租约、Checkpoint和重试。
- 使用Outbox保证任务状态与事件在本地事务中一致。
- 区分请求幂等、工具幂等和业务补偿。
- 建立请求、并发、Token和金额四类限额。
- 设计单Region、多Region、数据驻留和故障切换边界。
- 通过Trace、Metrics、Logs和版本矩阵定位质量与稳定性问题。
一、生产级分层架构
flowchart TD
A["Web、App、开放API和内部系统"] --> B["API Gateway/WAF"]
B --> C["入口层:认证、租户、限流、参数和文件"]
C --> D["AI编排层:场景、Prompt、Memory、RAG、Tool"]
D --> E["知识服务:解析、权限检索、Rerank和引用"]
D --> F["工具服务:鉴权、幂等、事务和审计"]
D --> G["模型网关:适配、路由、Deadline、配额和观测"]
G --> H["云模型Provider"]
G --> I["本地推理集群"]
E --> J["文档库、向量库和元数据"]
F --> K["订单、资产、采集、工单等业务系统"]
D --> L["治理:安全、评估、成本、版本和反馈"]| 层 | 负责什么 | 不负责什么 |
|---|---|---|
| Gateway/WAF | TLS、路由、基础防护、连接策略 | 不理解RAG和Prompt语义 |
| 入口层 | 用户、租户、场景准入、参数、请求配额 | 不直接拼接任意数据库结果 |
| 编排层 | 选择处理链、组织上下文、控制状态 | 不绕过工具直接修改业务库 |
| 知识服务 | 文档生命周期、ACL、召回、Rerank、引用 | 不让模型决定用户权限 |
| 工具服务 | 查询/写入业务能力、权限、幂等、审计 | 不盲信模型参数 |
| 模型网关 | Provider差异、模型路由、超时、限流、Usage | 不编写订单退款规则 |
| 治理层 | 版本、评估、安全、SLO、成本、反馈 | 不以日志代替权威业务事实 |
分层不是为了堆微服务。小项目可以在一个进程中按模块实现这些边界;流量、团队和故障域增长后再拆服务。关键是职责与证据分开,而不是部署单元越多越好。
二、一次同步请求怎样走
以“查询LIS字段含义并解释最近采集失败”为例:
flowchart TD
A["客户端发送问题"] --> B["Gateway生成/透传requestId"]
B --> C["认证用户、租户和权限"]
C --> D["参数、输入Token和请求限额"]
D --> E["场景路由:字段知识+实时采集"]
E --> F["RAG按ACL检索字段资料"]
E --> G["Tool按当前身份查询采集状态"]
F --> H["去重、Rerank和Token预算"]
G --> I["结果脱敏和结构化"]
H --> J["编排Prompt、资料和工具结果"]
I --> J
J --> K["模型网关选择满足能力的模型"]
K --> L["Provider调用和逐Token推理"]
L --> M["结构、引用、事实和安全校验"]
M --> N["结算Usage、记录版本和Trace"]
N --> O["返回答案、引用和requestId"]模型只负责基于已经授权的上下文组织答案。字段定义来自知识库,实时状态来自工具,权限来自后端,引用由应用绑定真实Chunk,模型不能自由决定这些事实。
三、每一步的输入和证据
| 阶段 | 输入 | 输出/证据 |
|---|---|---|
| 入口 | Token、请求、客户端元数据 | userId、tenantId、requestId |
| 场景路由 | 问题和准入配置 | scene、routeVersion、risk |
| RAG | 用户权限、查询 | chunkId、分数、索引/Embedding版本 |
| Tool | 当前身份、结构化参数 | toolCallId、业务号、状态、幂等键摘要 |
| Prompt | 模板、历史、资料、工具结果 | promptVersion、Token预算 |
| 模型网关 | 能力要求、Deadline | 实际模型、Provider requestId、Usage |
| 输出治理 | 原始响应、Schema、引用 | 校验结果、拒答/人工状态 |
| 响应 | 安全结果 | answer、references、traceId |
只保存最终回答不能排查“为什么答错”。需要知道模型究竟看到了哪些资料和工具事实,但日志必须脱敏、限权和设置保留期。
四、场景路由和模型路由不是同一个
4.1 场景路由
决定业务链:
GENERAL_QA 直接问答/Prompt
KNOWLEDGE_QA RAG
REALTIME_QUERY Tool查询
DIAGNOSIS Tool + RAG
WRITE_ACTION 计划、确认、幂等工具
ASYNC_DOCUMENT 异步解析与报告高风险词和动作由确定性规则兜底,不能完全依赖模型分类。例如退款、删除、改权限必须强制进入高风险流程。
4.2 模型路由
在确定业务链后,根据能力选择模型:
结构化输出能力
Tool Calling能力
多模态能力
上下文长度
质量门槛
数据驻留
延迟SLO
费用预算
当前配额和健康不能只按价格或随机轮询。备用模型若不支持JSON Schema或工具,就不能处理该场景。
五、Prompt与上下文编排
上下文通常包括:
System/安全规则
+ 场景模板
+ 当前用户问题
+ 必要会话历史
+ RAG资料
+ Tool定义和结果
+ 输出Schema
+ 输出预留编排层要做:
- 信任边界分离:规则不是资料,资料中的指令不能升级权限。
- Token预算:为各部分设置上限。
- 历史摘要:旧消息不无限累积。
- RAG去重和Rerank。
- 工具结果最小化和脱敏。
- Prompt版本和回滚。
- 输出Schema与业务校验。
六、Memory不是模型天然记忆
| 类型 | 数据 | 生命周期 |
|---|---|---|
| 短期对话 | 最近消息/摘要 | 会话级 |
| 任务状态 | Agent步骤、事实、审批 | 任务级 |
| 长期偏好 | 用户主动配置 | 可查询、修改、删除 |
| 业务事实 | 订单、资产、工单 | 业务系统权威 |
Memory由应用保存并重新注入,占上下文和费用。Memory Key必须包含租户与会话,删除和过期要可执行。模型声称“记得”不证明存储中存在事实。
七、模型网关的职责
flowchart TD
A["编排层标准请求"] --> B["能力与策略检查"]
B --> C["模型/Provider路由"]
C --> D["协议适配"]
D --> E["Deadline、并发和Token配额"]
E --> F["Provider调用"]
F --> G["响应/流事件归一化"]
G --> H["Usage结算、Metrics和Trace"]
H --> I["标准结果返回编排层"]模型网关通常负责:
- 标准Messages、Options、Tool和多模态请求。
- Provider字段和错误映射。
- 模型能力注册和路由。
- Deadline与分阶段超时。
- 请求、并发、Token和金额限额。
- 可恢复错误的有限重试。
- 熔断、Bulkhead和Fallback。
- Usage、成本、版本和审计元数据。
- 流式事件、取消和背压。
模型网关不应负责用户是否有权退款;那是业务工具的权限与状态机。
八、Deadline与超时预算
请求总Deadline先确定,再分配:
总Deadline 20秒
入口与编排 1秒
RAG 2秒
Rerank 1秒
Tool 3秒
模型首Token 8秒
输出与余量 5秒每阶段收到的是“剩余Deadline”,不是各自重新开始20秒,否则串行链路可能远超用户SLO。
区分:
| 超时 | 含义 |
|---|---|
| Connect | TCP/代理连接 |
| TLS | 握手和证书 |
| First Token | 流式首事件 |
| Idle Read | 流中多久没有新数据 |
| Total | 整个调用截止时间 |
| Tool Unknown | 写工具超时但可能已提交 |
九、重试、熔断和Bulkhead
9.1 重试分类
通常不重试:参数错误、401/403、明确内容拒绝、业务不存在。可条件重试:连接瞬时失败、部分429/5xx,但要尊重Retry-After、指数退避、抖动、最大次数和全局重试预算。
写工具超时不能直接重试,先按幂等键查询结果。
9.2 熔断
当某Provider持续失败,熔断器快速拒绝或路由到经验证备用,避免每个请求都等超时。Half-open用少量探测验证恢复。
9.3 Bulkhead
按Provider、模型和场景隔离并发。长推理任务不能占满所有槽位导致短问答也不可用。
十、四类限额不能只写QPS
| 限额 | 防止 |
|---|---|
| 请求速率 | 短时间请求洪峰 |
| 在途并发 | 长请求占满线程/连接/GPU槽位 |
| Token | 少量超长请求吃光算力和上下文 |
| 金额 | 高价模型、重试和长输出导致预算失控 |
典型流程:
请求前估算输入和最大输出
→ 预留Token/金额额度
→ 调用
→ 按真实Usage结算
→ 释放未使用额度
→ 处理进程崩溃未结算记录十一、同步、流式和异步怎么选
| 模式 | 适合 | 完成语义 | 关键风险 |
|---|---|---|---|
| 同步 | 分类、抽取、短问答 | HTTP响应即完成 | 总超时和线程占用 |
| SSE流式 | 聊天、长解释 | 流结束才完成 | 断连、缓冲、取消、中途错误 |
| 异步 | 文档、批量、Agent、长报告 | 任务状态完成 | 重试、恢复、重复执行、通知 |
11.1 同步
简单但调用链必须在Deadline内。适合结果必须完整校验后返回的JSON任务。
11.2 SSE流式
flowchart TD
A["客户端建立SSE"] --> B["后端调用模型stream"]
B --> C["Provider增量事件"]
C --> D["网关归一化"]
D --> E["输出治理/缓冲策略"]
E --> F["立即flush给客户端"]
F --> G{"完成、错误或断连"}
G -->|"继续"| C
G -->|"断连"| H["传播取消并停止计费任务"]
G -->|"结束"| I["记录Usage、finish和审计"]HTTP Header发出后,中途错误通常不能再改成500,应发送协议内错误事件并结束。Nginx、压缩和前端缓冲会制造“假流式”。
11.3 异步
客户端提交后立即获得 202 + taskId,通过轮询、SSE/WebSocket状态或通知获取结果。通知只是提示,任务表才是状态权威。
十二、异步任务状态机
flowchart TD
A["CREATED"] --> B["QUEUED"]
B --> C["RUNNING"]
C --> D{"执行结果"}
D -->|"成功"| E["SUCCEEDED"]
D -->|"可重试"| F["RETRY_WAIT"]
F --> B
D -->|"永久失败"| G["FAILED"]
C --> H["CANCEL_REQUESTED"]
H --> I["CANCELLED或无法取消"]
C --> J["WAITING_APPROVAL"]
J --> B状态更新需校验允许迁移和版本号。例如完成任务不能被迟到Worker覆盖回RUNNING。
任务字段至少包括:
taskId、tenantId、userId、scene
status、version、priority
inputRef、resultRef
attempt、maxAttempts、nextRunAt
leaseOwner、leaseUntil
deadline、cancelRequested
prompt/model/rag/tool/policy版本
Token和费用
errorCode、safeError
createdAt、startedAt、finishedAt十三、Worker租约和并发领取
flowchart TD
A["多个Worker查询可运行任务"] --> B["数据库原子抢占/Skip Locked"]
B --> C["写leaseOwner和leaseUntil"]
C --> D["Worker执行并周期续租"]
D --> E{"执行完成"}
E -->|"是"| F["按version提交结果"]
E -->|"Worker崩溃"| G["租约过期"]
G --> H["其他Worker重新领取"]租约避免两个Worker同时长期执行,但不能替代工具和业务幂等:Worker可能在工具提交成功后、保存Checkpoint前崩溃。
十四、Checkpoint和长任务恢复
Checkpoint记录:
- 已完成步骤和当前步骤。
- 结构化事实和安全Observation。
- 每次模型/工具调用ID与状态。
- 幂等键摘要和业务结果号。
- 已用Token、费用和剩余预算。
- 待审批计划与Hash。
- 下一执行时间和错误分类。
恢复时从最后已提交Checkpoint继续,不能仅依赖最后一条自然语言消息判断外部动作是否成功。
十五、Outbox为什么需要
场景:任务状态改成SUCCEEDED后要发“任务完成”事件。如果数据库提交成功、MQ发送失败,用户永远收不到通知;若先发MQ再提交,消费者可能看不到结果。
同一本地事务写:
ai_task.status = SUCCEEDED
ai_outbox(eventId, taskId, type, payloadRef, status=NEW)后台Publisher读取Outbox并至少一次发送,消费者按eventId幂等。Outbox解决同一个数据库事务内状态和待发送事件一致性,不会自动原子提交两个独立数据库。
十六、幂等和结果不确定
16.1 请求幂等
客户端重试创建任务时携带业务幂等键,数据库唯一约束返回原taskId。
16.2 工具幂等
创建工单、发送通知等使用服务端幂等键和业务唯一约束。
16.3 模型调用
模型生成通常非确定性。超时重试可能产生不同文本和双倍费用,不能简单当作幂等。记录attempt并按场景决定是否重试。
16.4 UNKNOWN
写工具超时只证明没收到响应,状态应为UNKNOWN并查询执行结果,不能直接标FAILED后重做。
十七、可运行Demo:受预算的模型网关
下面用标准库模拟能力路由、Deadline、并发和Usage结算:
from dataclasses import dataclass
from threading import BoundedSemaphore
import time
@dataclass(frozen=True)
class ModelCapability:
name: str
supports_tools: bool
supports_json: bool
max_context: int
cost_per_1k_tokens_fen: float
@dataclass(frozen=True)
class RequestPolicy:
require_tools: bool
require_json: bool
input_tokens: int
max_output_tokens: int
max_cost_fen: float
deadline_monotonic: float
MODELS = [
ModelCapability("fast-model", False, True, 16_000, 0.5),
ModelCapability("tool-model", True, True, 64_000, 2.0),
]
class ModelGateway:
def __init__(self, max_concurrency: int = 2):
self._slots = BoundedSemaphore(max_concurrency)
def choose(self, policy: RequestPolicy) -> ModelCapability:
required_tokens = policy.input_tokens + policy.max_output_tokens
for model in MODELS:
if policy.require_tools and not model.supports_tools:
continue
if policy.require_json and not model.supports_json:
continue
if required_tokens > model.max_context:
continue
max_cost = required_tokens / 1000 * model.cost_per_1k_tokens_fen
if max_cost <= policy.max_cost_fen:
return model
raise RuntimeError("没有同时满足能力、上下文和预算的模型")
def call(self, policy: RequestPolicy) -> dict:
remaining = policy.deadline_monotonic - time.monotonic()
if remaining <= 0:
raise TimeoutError("调用前Deadline已耗尽")
if not self._slots.acquire(timeout=remaining):
raise TimeoutError("等待并发槽位超时")
try:
model = self.choose(policy)
# 真实实现调用Provider,并按剩余Deadline设置连接、首Token和总超时。
actual_input, actual_output = policy.input_tokens, 300
actual_cost = (
(actual_input + actual_output)
/ 1000
* model.cost_per_1k_tokens_fen
)
return {
"model": model.name,
"usage": {"input": actual_input, "output": actual_output},
"actual_cost_fen": actual_cost,
"remaining_ms": int(
(policy.deadline_monotonic - time.monotonic()) * 1000
),
}
finally:
self._slots.release()
if __name__ == "__main__":
gateway = ModelGateway(max_concurrency=2)
policy = RequestPolicy(
require_tools=True,
require_json=True,
input_tokens=4_000,
max_output_tokens=1_000,
max_cost_fen=20,
deadline_monotonic=time.monotonic() + 3,
)
print(gateway.call(policy))Demo是单进程教学实现。生产并发和额度需要分布式/持久化状态,预留后按真实Usage结算,并处理进程崩溃未释放额度。
十八、可运行Demo:可恢复任务状态
from dataclasses import dataclass
from enum import Enum
class Status(str, Enum):
CREATED = "CREATED"
RUNNING = "RUNNING"
RETRY_WAIT = "RETRY_WAIT"
SUCCEEDED = "SUCCEEDED"
FAILED = "FAILED"
ALLOWED = {
Status.CREATED: {Status.RUNNING},
Status.RUNNING: {Status.RETRY_WAIT, Status.SUCCEEDED, Status.FAILED},
Status.RETRY_WAIT: {Status.RUNNING, Status.FAILED},
Status.SUCCEEDED: set(),
Status.FAILED: set(),
}
@dataclass
class Task:
task_id: str
status: Status = Status.CREATED
version: int = 0
attempt: int = 0
def transition(self, expected_version: int, target: Status) -> None:
if self.version != expected_version:
raise RuntimeError("乐观锁冲突:任务已被其他Worker更新")
if target not in ALLOWED[self.status]:
raise ValueError(f"非法状态迁移:{self.status} -> {target}")
self.status = target
self.version += 1
if target == Status.RUNNING:
self.attempt += 1
if __name__ == "__main__":
task = Task("ai-task-001")
task.transition(0, Status.RUNNING)
task.transition(1, Status.RETRY_WAIT)
task.transition(2, Status.RUNNING)
task.transition(3, Status.SUCCEEDED)
print(task)数据库实现应使用 UPDATE ... WHERE task_id=? AND version=? AND status=?,检查影响行数,而不是先查后改。
十九、取消语义
用户取消后:
- 任务写
cancelRequested=true。 - Worker在步骤边界检查。
- 向模型流传播取消。
- 尚未执行的工具不再执行。
- 已提交写工具不能靠取消回滚,需补偿或说明无法取消。
- 记录取消人、时间和最终状态。
“前端关闭页面”不自动取消后端模型计费,SSE断连必须显式传播。
二十、缓存设计
缓存Key不能只有问题文本,至少考虑:
tenantId/权限摘要
scene
normalizedQuestion
promptVersion
model/adapterVersion
knowledgeIndexVersion
toolSnapshotVersion
safetyPolicyVersion
decodingOptions实时订单和高风险输出通常不适合直接缓存最终答案。Embedding、文档解析和确定性只读结果可按版本缓存。缓存命中也要记录,避免评估新模型时实际返回旧答案。
二十一、可观测性
21.1 Trace
Span建议:
ai.request
├── auth/quota
├── scene.route
├── rag.retrieve
├── rag.rerank
├── tool.call
├── prompt.compose
├── model.queue
├── model.call
└── output.validate21.2 Metrics
- QPS、并发、队列。
- 成功率、429、超时、取消。
- RAG召回/Rerank耗时。
- Tool失败和UNKNOWN。
- TTFT、TPOT、总耗时、P95/P99。
- 输入输出Token和费用。
- JSON/引用/安全失败。
- 人工接管、反馈和任务成功率。
21.3 Logs
记录requestId、tenant、scene、版本、chunkId、toolCallId、错误分类和Usage。Prompt、文档、工具结果和模型输出按数据策略脱敏/限权,不能默认全量打印。
二十二、版本矩阵
一次回答可复现需要:
applicationCommit
sceneRouteVersion
promptVersion
memoryPolicyVersion
modelAlias和实际Revision
adapter/quantization/engineVersion
embedding/index/chunk/rerankVersion
toolSchema和业务接口Version
safetyPolicyVersion
decodingOptions
experimentId只记录模型名无法判断质量变化来自哪里。
二十三、单Region与多Region
23.1 单Region高可用
多实例、负载均衡、数据库高可用、队列和Provider降级。先把单Region恢复、幂等和数据备份做好,再考虑多Region。
23.2 多Region难点
| 问题 | 说明 |
|---|---|
| 数据驻留 | 敏感Prompt/文档是否允许跨区 |
| 会话/任务 | 状态复制延迟和写冲突 |
| 向量索引 | 版本和同步一致性 |
| 配额 | 全局额度如何避免双花 |
| 幂等 | 同一请求切区后不能重复写业务 |
| Provider | Region能力、模型和配额不同 |
| 路由 | 故障切换是否保持会话粘性 |
多Region Active-Active不是自动更可靠。跨区网络、复制和一致性会增加故障模式。高风险写操作可以使用单写Region或业务系统全局幂等。
二十四、灾备与降级
降级层次:
关闭非必要Rerank/长历史(质量评估后)
→ 路由到经验证备用模型
→ 返回只读RAG结果/固定提示
→ 异步排队
→ 拒绝并转人工高风险场景宁可拒绝或人工,不要使用未验证小模型。灾备演练要覆盖Provider全挂、向量库故障、队列积压、模型OOM和配置回滚。
二十五、商业架构示例:采集异常助手
flowchart TD
A["运维提交taskId"] --> B["认证和任务对象权限"]
B --> C["工具查询脱敏任务状态"]
C --> D["按errorCode检索Runbook"]
D --> E["模型生成原因、证据和建议"]
E --> F["引用、Schema和安全校验"]
F --> G{"是否建议创建工单"}
G -->|"否"| H["返回分析"]
G -->|"是"| I["生成待确认计划"]
I --> J["用户确认后幂等创建"]
J --> K["Outbox发布完成事件"]第一版不开放自动重跑采集任务。Agent只做分析和工单计划,重跑进入确定性审批工作流。
二十六、生产Runbook
26.1 AI答错
按requestId检查场景路由、Prompt/模型版本、RAG chunk与权限、Tool事实、输出校验和缓存。不要直接换模型。
26.2 TTFT突然升高
拆排队、RAG、Tool、Prompt长度、Provider连接和Prefill;检查并发槽、限流和Region。TTFT正常但总耗时高则看输出长度和TPOT。
26.3 SSE最后一次性返回
逐跳记录事件时间:Provider、网关、应用、Nginx和浏览器。检查响应缓冲、压缩和flush。后端收到增量不代表前端实时看到。
26.4 异步任务重复执行
沿taskId、attempt、leaseOwner、toolCallId、幂等键和业务号还原。租约过期重领是正常可能性,写工具必须业务幂等。
26.5 任务永久RUNNING
检查租约、Heartbeat、Worker进程、Checkpoint事务、队列和超时扫描。过期租约应重排或转人工。
26.6 状态成功但没有通知
检查同事务Outbox是否存在、Publisher租约、MQ、消费者Inbox/幂等和通知渠道。任务状态是事实,通知只是派生事件。
26.7 Provider切换后解析失败
保存脱敏原始响应/SSE事件,比较Tool、Reasoning、Usage、finish reason和错误结构;修Provider适配契约,不把差异泄漏到业务Controller。
26.8 成本突然增长
检查请求、并发、输入/输出Token、历史、RAG TopK、工具结果、重试、缓存、模型路由和异步重复任务,按scene/tenant/model分解。
26.9 多Region出现重复写
检查全局幂等键、任务主Region、复制延迟、故障切换时间和业务唯一约束。流量切换不能替代业务系统去重。
二十七、常见误区
所有AI能力都放模型网关
错误。网关管模型调用,业务权限、RAG和工具各有边界。
有QPS限流就够了
错误。长请求还需并发、Token和金额限额。
SSE让模型总耗时更短
错误。主要改善首Token感知,并增加长连接治理。
Worker租约解决重复业务写
错误。崩溃窗口仍存在,工具和业务表必须幂等。
Outbox等于分布式事务万能方案
错误。它保证同一数据库中的状态和事件记录原子,跨数据库仍需消息、幂等和对账。
多Region一定更可靠
错误。状态、配额、索引和幂等复杂度增加,需明确故障模型。
二十八、面试标准回答
一次AI请求完整链路
请求经过网关、认证、租户、参数和四类配额,编排层先做场景路由,按需以ACL检索RAG并调用受控工具,再按Token预算组装Prompt;模型网关按能力和SLO选择模型,执行Deadline、限流和Provider适配;返回后做Schema、引用、事实和安全校验,最后结算Usage并记录完整版本与Trace。
模型网关有什么作用
模型网关屏蔽Provider协议差异,统一能力注册、模型路由、Deadline、请求/并发/Token/金额限额、有限重试、熔断、流式事件、Usage和版本观测。它不负责订单权限和退款规则,业务动作仍由工具服务控制。
异步AI任务怎样防重复和恢复
任务使用状态机、版本乐观锁和Worker租约领取,每个步骤保存Checkpoint;请求创建、工具写入和消息消费分别做持久化幂等。任务状态和Outbox事件在同一本地事务提交,Worker崩溃后租约过期可重领,并根据工具幂等结果继续,而不是重复执行。
为什么限流不能只有QPS
AI请求时长和Token差异大,少量长请求也能占满连接、GPU槽位和预算。生产同时限制请求速率、在途并发、Token和金额,调用前预留,按真实Usage结算,并处理崩溃未释放额度。
二十九、学习验收
不看答案完成:
- 画出入口、编排、知识、工具、模型和治理层。
- 为六类问题设计场景路由。
- 给三个模型定义能力并实现能力门槛路由。
- 为20秒Deadline分配RAG、Tool和模型预算。
- 区分请求、并发、Token和金额限额。
- 运行模型网关Demo并制造预算不满足。
- 设计SSE错误和断连取消协议。
- 运行状态机Demo并制造非法迁移和乐观锁冲突。
- 设计Worker租约、Checkpoint和Outbox表。
- 演练工具超时UNKNOWN与幂等查证。
- 写出完整版本矩阵和Trace Span。
- 演练Provider、向量库、队列和Region故障。
