代码语言

知识点思维导图

29 个知识节点

生产工程(06) - AI 应用接口设计

读完后,你应能完成以下任务:

  • 绘制“生产工程(06) - AI 应用接口设计 / 门卫的顺序:requestId → 鉴权 → 限流 → 业务”的关键对象与数据流,解释“因为非法请求根本不该消耗你的限流配额,也不该进入任何后续逻辑——越早挡掉越好。”,并用源码位置、日志或 Trace 标注证据。
  • 为“生产工程(06) - AI 应用接口设计 / ① requestId:把散落的日志串成一条链”设计正常与异常输入,验证“这是排查 AI 应用坏 case 的命脉。”,输出首个偏差位置与回归测试结果。
  • 实现“生产工程(06) - AI 应用接口设计 / ③ 限流:滑动窗口挡住高频请求”的最小代码或配置,检验“限流防止单个用户(或攻击者)把后端刷爆、把模型费用刷上天。”,输出命令、结果与 Diff,并说明不适用边界。

一、AI 应用接口设计的真实应用场景

你的 AI 问答接口上线了,前面几篇的能力都串起来了。然后出三件事:

  1. 用户反馈「有时候回答很奇怪」,你想查那一次到底发生了啥——但日志里几千条混在一起,根本定位不到是哪一次请求。
  2. 有人拿到你的接口地址,写脚本一秒钏几十次,模型调用费蹭蹭涨。
  3. 接口没鉴权,谁都能调,你的模型额度在给陌生人花钱。

这三件事,对应 AI 接口必须有的三道门卫:requestId(能追踪)、限流(防刷爆)、鉴权(挡非法)。业务逻辑写得再好,少了这三样就不能上生产。

二、门卫的顺序:requestId → 鉴权 → 限流 → 业务

一个请求进来,要依次过这几关,顺序有讲究:

请求进来
  ↓
① 分配 requestId       —— 第一件事,后面所有日志都带上它
  ↓
② 鉴权(401)          —— 非法身份直接挡掉,不浪费后续任何资源
  ↓
③ 限流(429)          —— 合法用户也不能无限刷
  ↓
④ 业务逻辑(含参数校验 400)
  ↓
返回(带 requestId)

为什么鉴权在限流前?因为非法请求根本不该消耗你的限流配额,也不该进入任何后续逻辑——越早挡掉越好。

2.1 ① requestId:把散落的日志串成一条链

每个请求一进来就生成一个唯一 id,前端、后端、模型调用的日志全带上它。出问题时,拿这个 id 一搜,整条链路的日志就拼齐了:

这是排查 AI 应用坏 case 的命脉。AI 输出不稳定,没有 requestId 串联,复现和定位基本靠猜。

2.2 ② 鉴权:只认后端白名单

鉴权必须在后端做,且只信你自己的白名单,绝不信任前端传来的任何身份声明:

2.3 ③ 限流:滑动窗口挡住高频请求

限流防止单个用户(或攻击者)把后端刷爆、把模型费用刷上天。常用滑动窗口:记录每个 key 最近的请求时间,窗口内超过上限就拒绝:

三、用对状态码,前端才好处理

不同失败要返回不同状态码,前端据此决定怎么应对:

场景 状态码 前端该做什么
没登录 / Key 无效 401 跳登录,重试无意义
触发限流 429 提示「请求太频繁」,等一会再试
参数错(缺字段) 400 提示用户改输入,重试无意义
服务端故障 500 可重试
正常 200 展示结果

把 401、429、400 全返成 500,前端就分不清「该重试」还是「该改请求」,体验和稳定性都垮。

四、统一响应结构

所有接口返回同一套结构,前端一套解析逻辑通吃:

request_id 永远带上(出错时前端能上报)、code 标明结果、成功放 data、失败放 error

五、工程上真正会踩的坑

  • 限流状态存内存。单机没问题,多实例部署时每个实例各算各的,实际放行量是配置的好几倍。多实例要用 Redis 做共享限流。
  • 鉴权信任前端传的 userId。前端传 {userId: "admin"} 你就当真,等于没鉴权。身份只能从后端校验过的 token 推出来。
  • 错误码乱用。全返 200 然后在 body 里写 success: false,或者啥错都返 500。前端没法按状态码分流处理。
  • 日志记了明文敏感数据。requestId 日志里把用户手机号、完整 prompt 原样打出来,违规也有泄露风险。日志要脱敏。
  • 把模型原始响应直接透传前端。模型返回的格式可能变、可能含内部信息。后端要包成自己稳定的结构再返回,别让前端直接吃模型原文。

六、一句话面试答法

AI 接口除了业务逻辑还要设计什么? 三道门卫加一套规范。门卫按顺序:每个请求先分配 requestId 串联全链路日志,这是排查 AI 坏 case 的命脉;再鉴权,只认后端白名单不信前端传的身份,挡掉非法请求返 401;再限流,用滑动窗口防止刷爆后端和模型费用,超了返 429。规范上:状态码要用对,401/429/400/500 让前端能区分该重试还是该改请求;响应结构统一成 request_id + code + data/error;日志脱敏;模型响应包成自己的结构再返回,不直接透传。多实例部署限流状态要放 Redis 共享。

七、动手实践:19 AI 应用接口设计

一个 AI 接口除了业务逻辑,还得有三层「门卫」:requestId 追踪、鉴权头校验、限流。这里用一组中间件函数模拟请求依次过关,离线可跑。

7.1 在线运行

零依赖,纯标准库。

7.2 预期输出

=== 场景 1:没带 Authorization(鉴权失败 401)===
匿名请求
  -> {'request_id': 'req_61ae6ab9', 'code': 401, 'error': '缺少或格式错误的 Authorization 头'}

=== 场景 2:错误的 API Key(鉴权失败 401)===
乱填 key
  -> {'request_id': 'req_3eb67923', 'code': 401, 'error': '无效的 API Key'}

=== 场景 3:合法用户连续请求,第 4 次触发限流(429)===
alice 第 1 次请求
  -> {'request_id': 'req_f2f79080', 'code': 200, 'data': {'answer': '(回答给 alice)你的问题「问题1」已收到。'}}

alice 第 2 次请求
  -> {'request_id': 'req_c8f04d45', 'code': 200, 'data': {'answer': '(回答给 alice)你的问题「问题2」已收到。'}}

alice 第 3 次请求
  -> {'request_id': 'req_48cf4f23', 'code': 200, 'data': {'answer': '(回答给 alice)你的问题「问题3」已收到。'}}

alice 第 4 次请求
  -> {'request_id': 'req_7af3b55d', 'code': 429, 'error': '触发限流,请 10.0s 后重试'}

=== 场景 4:合法但参数为空(400)===
bob 空消息
  -> {'request_id': 'req_7307f7b8', 'code': 400, 'error': 'message 不能为空'}

要点:每个请求都有 requestId;先鉴权再限流再业务;不同失败对应不同 code。

每个响应都带 request_id(每次运行的随机值不同);alice 连发 3 次正常、第 4 次被限流返回 429;不同失败对应不同状态码(401/429/400),前端据此区别处理。

7.3 代码↔概念对应

概念 在 main.py 哪里
每个请求分配 requestId gen_request_id
鉴权:校验 Authorization 头 + Key 白名单 check_auth
限流:滑动窗口算法 check_rate_limit
门卫顺序:requestId → 鉴权 → 限流 → 业务 handle_request
统一响应结构(request_id + code + data/error) handle_request 的返回值

7.4 动手改

  • MAX_REQUESTS 改成 5,看 alice 要发到第 6 次才被限流。
  • 把鉴权和限流的顺序对调,思考为什么应该先鉴权(非法请求不该消耗限流配额,也不该进任何后续逻辑)。
  • 真实项目里 request_history 存内存只适合单机,多实例部署要换成 Redis;API_KEYS 白名单也应存数据库。

7.5 可运行源码:AI 应用接口设计

main.py

八、总结

  • 门卫的顺序:requestId → 鉴权 → 限流 → 业务:因为非法请求根本不该消耗你的限流配额,也不该进入任何后续逻辑——越早挡掉越好。
  • 用对状态码,前端才好处理:把 401、429、400 全返成 500,前端就分不清「该重试」还是「该改请求」,体验和稳定性都垮。
  • 统一响应结构:request_id 永远带上(出错时前端能上报)、code 标明结果、成功放 data、失败放 error。
  • 工程上真正会踩的坑:单机没问题,多实例部署时每个实例各算各的,实际放行量是配置的好几倍。
  • 一句话面试答法:门卫按顺序:每个请求先分配 requestId 串联全链路日志,这是排查 AI 坏 case 的命脉;
  • ① requestId:把散落的日志串成一条链:这是排查 AI 应用坏 case 的命脉。

学完自测

选择所有正确答案;提交后逐项核对判断依据。

1在“AI 应用接口设计”中,需要同时满足“AI 应用接口设计的真实应用场景”与“门卫的顺序:requestId → 鉴权 → 限流 → 业务”。给定正文约束“业务逻辑写得再好,少了这三样就不能上生产。”,哪些判断保持了原有处理机制?多选
2“AI 应用接口设计”出现偏差:“在“AI 应用接口设计 / ① requestId:把散落的日志串成一条链”中,即使不满足“每个请求一进来就生成一个唯一 id,前端、后端、模型调用的日志全带上它”,结果与副作用仍会保持不变。”已成为实际行为。围绕“① requestId:把散落的日志串成一条链”与“② 鉴权:只认后端白名单”,哪些判断能定位被改变的职责或边界?多选
3评审“AI 应用接口设计”方案时,验收条件包含“限流防止单个用户(或攻击者)把后端刷爆、把模型费用刷上天。”。关于“③ 限流:滑动窗口挡住高频请求”与“用对状态码,前端才好处理”的哪些决策符合正文机制?多选