Spring AI 上生产:限流熔断、密钥与成本治理、私有化/混合部署、降级与 Prompt 灰度架构全解
系列:Spring AI 深入浅出(第 22 篇)
版本:Spring AI 2.0.1 / Spring Boot 4.1.x / JDK 21
标签:#SpringAI #生产架构 #高可用 #成本治理
前置阅读:第 19 篇《可观测性》、第 21 篇《安全》
预计字数:7000 字|架构总图 + 降级灰度流程 + 踩坑 FAQ
本文将解决:Demo 到生产的最后一步,是可用性、成本、合规、灰度的系统设计。本文给出可落地的架构全解。
你将学到:
- 生产架构总览拓扑
- 限流熔断与降级
- 密钥与成本治理
- 私有化/混合部署
- Prompt 版本与灰度
- 结合企业内部系统接入的实战案例
一、版本标注
本文基于 Spring AI 2.0.1 / Boot 4.1 / JDK 21。本文是架构设计篇,复用前 21 篇的能力组件,聚焦"怎么拼成生产系统"。
二、生产架构总览
#mermaid-svg-GxZhKyiO9zC9LP96{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GxZhKyiO9zC9LP96 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GxZhKyiO9zC9LP96 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GxZhKyiO9zC9LP96 .error-icon{fill:#552222;}#mermaid-svg-GxZhKyiO9zC9LP96 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GxZhKyiO9zC9LP96 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GxZhKyiO9zC9LP96 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GxZhKyiO9zC9LP96 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GxZhKyiO9zC9LP96 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GxZhKyiO9zC9LP96 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GxZhKyiO9zC9LP96 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GxZhKyiO9zC9LP96 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GxZhKyiO9zC9LP96 .marker.cross{stroke:#333333;}#mermaid-svg-GxZhKyiO9zC9LP96 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GxZhKyiO9zC9LP96 p{margin:0;}#mermaid-svg-GxZhKyiO9zC9LP96 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GxZhKyiO9zC9LP96 .cluster-label text{fill:#333;}#mermaid-svg-GxZhKyiO9zC9LP96 .cluster-label span{color:#333;}#mermaid-svg-GxZhKyiO9zC9LP96 .cluster-label span p{background-color:transparent;}#mermaid-svg-GxZhKyiO9zC9LP96 .label text,#mermaid-svg-GxZhKyiO9zC9LP96 span{fill:#333;color:#333;}#mermaid-svg-GxZhKyiO9zC9LP96 .node rect,#mermaid-svg-GxZhKyiO9zC9LP96 .node circle,#mermaid-svg-GxZhKyiO9zC9LP96 .node ellipse,#mermaid-svg-GxZhKyiO9zC9LP96 .node polygon,#mermaid-svg-GxZhKyiO9zC9LP96 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GxZhKyiO9zC9LP96 .rough-node .label text,#mermaid-svg-GxZhKyiO9zC9LP96 .node .label text,#mermaid-svg-GxZhKyiO9zC9LP96 .image-shape .label,#mermaid-svg-GxZhKyiO9zC9LP96 .icon-shape .label{text-anchor:middle;}#mermaid-svg-GxZhKyiO9zC9LP96 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GxZhKyiO9zC9LP96 .rough-node .label,#mermaid-svg-GxZhKyiO9zC9LP96 .node .label,#mermaid-svg-GxZhKyiO9zC9LP96 .image-shape .label,#mermaid-svg-GxZhKyiO9zC9LP96 .icon-shape .label{text-align:center;}#mermaid-svg-GxZhKyiO9zC9LP96 .node.clickable{cursor:pointer;}#mermaid-svg-GxZhKyiO9zC9LP96 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GxZhKyiO9zC9LP96 .arrowheadPath{fill:#333333;}#mermaid-svg-GxZhKyiO9zC9LP96 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GxZhKyiO9zC9LP96 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GxZhKyiO9zC9LP96 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GxZhKyiO9zC9LP96 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GxZhKyiO9zC9LP96 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GxZhKyiO9zC9LP96 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GxZhKyiO9zC9LP96 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GxZhKyiO9zC9LP96 .cluster text{fill:#333;}#mermaid-svg-GxZhKyiO9zC9LP96 .cluster span{color:#333;}#mermaid-svg-GxZhKyiO9zC9LP96 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GxZhKyiO9zC9LP96 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GxZhKyiO9zC9LP96 rect.text{fill:none;stroke-width:0;}#mermaid-svg-GxZhKyiO9zC9LP96 .icon-shape,#mermaid-svg-GxZhKyiO9zC9LP96 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GxZhKyiO9zC9LP96 .icon-shape p,#mermaid-svg-GxZhKyiO9zC9LP96 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GxZhKyiO9zC9LP96 .icon-shape rect,#mermaid-svg-GxZhKyiO9zC9LP96 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GxZhKyiO9zC9LP96 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GxZhKyiO9zC9LP96 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GxZhKyiO9zC9LP96 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户
网关
限流/鉴权/熔断
Spring AI 应用
模型
云端/本地
向量库
缓存
密钥服务
监控/审计
关键:AI 调用不是孤立的,要融入现有的网关、鉴权、监控体系,而不是另起炉灶。
三、限流与熔断
AI 模型接口不稳定 + 按量计费,必须限流熔断:
- 限流:网关/应用层对 AI 调用限流(防刷、防成本失控),可配 Resilience4j 或网关限流。
- 熔断:模型接口连续失败/超时时熔断,快速失败而不是拖垮上游。
- 降级:熔断后降级到兜底逻辑(缓存回复、模板回复、转备胎模型)。
java
// 思路:用 Resilience4j 给 AI 调用包一层熔断/限流
// 精确配置以 Resilience4j + Spring Boot 集成文档为准
四、密钥与成本治理
- 密钥管理:Key 放密钥服务(Vault 等),轮换、最小权限、用量告警(呼应第 21 篇)。
- 成本预算与配额:按租户/部门设 token 预算,超预算降级或拦截(复用第 6 篇 token 预算 Advisor)。
- 成本看板:用量 + 单价 → 成本实时看板(第 19 篇),成本异常自动告警。
五、私有化 / 混合部署
合规敏感的企业(金融、政务)要求数据不出域:
| 形态 | 说明 | 适用 |
|---|---|---|
| 纯云端 | 全用云端模型 | 通用、非敏感 |
| 纯私有化 | 本地 Ollama/vLLM 跑开源模型 | 强合规、数据不出域 |
| 混合 | 敏感数据走本地,通用走云端 | 兼顾成本与合规(最常用) |
混合部署要点:按数据敏感度路由------敏感请求走本地模型,非敏感走云端。Spring AI 的模型抽象(第 3 篇)让"路由到哪个模型"变成配置 + 少量路由逻辑。
六、模型降级兜底
生产必须考虑"主模型挂了怎么办":
- 多模型冗余:主模型失败,自动切备胎模型(不同厂商)。
- 超时降级:超过阈值,降级为缓存/模板回复。
- 质量兜底:模型返回异常(空、格式错),走结构化输出的自纠正 + 最终兜底。
java
// 思路:主备模型 + 降级兜底(伪代码)
try {
return primaryClient.prompt().user(q).call().content();
} catch (Exception e) {
log.warn("主模型失败,切备胎", e);
return fallbackClient.prompt().user(q).call().content();
}
七、Prompt 版本与灰度
呼应第 5 篇的提示词工程化,生产上要灰度:
- 多版本并存:提示词 v1/v2 都在库里。
- 灰度路由:按租户/比例把部分流量打到 v2。
- 观察对比:看 v2 的效果指标(结合第 20 篇评估),好就全量,差就回滚。
java
// 思路:按比例/租户路由到不同 prompt 版本(伪代码)
String version = grayRouter.route(userId); // 返回 v1 或 v2
String prompt = promptRepo.get("summarize", version);
八、企业内部系统接入(真实案例增强可信度)
架构师视角的加分点:结合自身 Java/物联网中台背景,讲一个真实接入案例。典型路径:
- 识别可 AI 化的高频场景(如"查设备告警""查订单状态")
- 用 Tool 暴露中台能力(第 14 篇):把中台查询/操作封装成工具
- 统一接入:ChatClient 挂工具 + 记忆 + 鉴权,套上前文的限流/审计/灰度
- 灰度上线:先内部小流量,评估达标再放量
建议在这篇里放一张你真实中台的"AI 接入架构图",比任何说教都有说服力。
九、原理图解:生产架构全貌
渲染错误: Mermaid 渲染失败: Parse error on line 14: ... 支撑层 F向量库 G缓存 H密钥服务 I监控 ----------------------^ Expecting 'SEMI', 'NEWLINE', 'EOF', 'AMP', 'START_LINK', 'LINK', 'LINK_ID', got 'NODE_STRING'
十、踩坑 FAQ
坑 1:模型接口不稳定,拖垮上游
现象 :模型偶尔慢/失败,导致整个请求链路雪崩。
原因 :没做熔断和超时。
解决:加熔断 + 超时 + 降级,模型失败快速失败,不拖垮上游。
坑 2:成本失控
现象 :AI 调用量上来后,账单爆了。
原因 :没设预算配额,没监控成本。
解决:按租户设 token 预算 + 成本看板 + 超预算告警/降级。
坑 3:私有化部署与云端能力不对齐
现象 :切到本地模型后,某些能力(多模态/工具)效果骤降。
原因 :开源模型能力 ≠ 云端顶级模型。
解决:混合部署,敏感数据走本地、强能力走云端;按场景选型。
坑 4:灰度路由状态不一致
现象 :同一用户一会儿 v1 一会儿 v2,体验割裂。
原因 :灰度路由没按稳定维度(如 userId 哈希)分流。
解决:用稳定维度做一致性路由,同一用户固定在一个版本。
坑 5:降级兜底没测过,真出事用不上
现象 :主模型挂了,降级逻辑也报错。
原因 :降级路径没演练。
解决:定期演练降级,兜底逻辑保持简单可靠。
十一、小结与合集导航
本篇把前 21 篇的能力拼成了生产系统:
- 限流熔断 + 降级,扛住模型不稳定
- 密钥 + 成本治理,控住账单
- 私有化/混合部署,兼顾合规与能力
- Prompt 灰度 + 评估,稳定迭代
- 内部系统接入,落到真实场景
下一篇:《复盘开源项目》------把整套能力整合成一个企业级 AI 助手,开源收口。
十二、互动钩子
投票:你现在 AI 应用是什么部署形态?
- 还没上生产
- 纯云端
- 纯私有化
- 混合部署
评论区聊聊你的生产部署心得;源码见置顶评论。