楼层: 首页/ 软件技术/ Spring AI/ 生产部署与最佳实践
十一

生产部署与最佳实践

Production Best Practices

本地跑通和上线是两回事。大模型接口会限流、会超时、会抽风,你的应用必须扛得住。下面是上线清单。

事项怎么做
API Key 安全不硬编码,走环境变量 / Nacos / 云密钥管理服务。
限流降级用 Sentinel 保护,模型接口挂了返回兜底话术,别让用户看到 500。
缓存相同 Prompt 结果缓存(Redis),省钱提速。
异步处理长任务别同步等,提交后异步处理、轮询结果。
日志监控记录每次调用的 Prompt、token 数、耗时、成本,出问题能查。
错误处理网络超时、模型返回空、JSON 解析失败,都要兜底。
安全防 Prompt 注入,敏感数据别发给模型。
容器化打 Docker 镜像,跟 Spring Cloud 那套一致。

缓存:相同问题别重复花钱

客服里很多问题是重复的——"退货政策是啥"被问一万次,每次都调大模型就是一万次钱。把 Prompt 当 key,结果当 value 存 Redis,第二次直接返回缓存。注意:缓存 key 要把 system prompt 和用户输入一起 hash,别只按用户问的话存,因为不同人设下答案不同。

手写一个简单缓存切面(思路)

public String ask(String q) { String key = "ai:" + DigestUtils.md5DigestAsHex(systemPrompt + q); String cached = redis.get(key); if (cached != null) return cached; // 命中缓存,直接返回 String ans = chatClient.prompt(q).call().content(); redis.setex(key, 3600, ans); // 存一小时 return ans; }

容器化部署

跟普通 Spring Boot 应用一样打镜像。注意 API Key 走环境变量,别打进镜像。

Dockerfile

FROM eclipse-temurin:17-jre COPY target/ai-cs.jar app.jar # API Key 通过环境变量传,不写死在镜像里 ENTRYPOINT ["java", "-jar", "/app.jar"]

异步处理与错误兜底

调大模型可能要几秒,同步等会占着线程。长任务(比如"总结这份 100 页报告")应该异步:提交任务立刻返回,后台慢慢跑,前端轮询结果。另外模型接口会超时、会报 5xx,必须 try-catch 兜底,别让用户看到一片白屏。

错误兜底写法

public String askSafely(String q) { try { return chatClient.prompt(q).call().content(); } catch (Exception e) { // 模型挂了、超时了、限流了,返回兜底话术 log.error("调大模型失败", e); return "客服小助手暂时开小差了,请稍后再试或转人工。"; } }

日志与监控:每一次调用都要留痕

AI 应用出问题时,你得知道:用户问了啥、发给模型的 Prompt 是啥、模型回了啥、花了多少 token、耗时多久。这些全记日志,既能 debug,又能算成本。Spring AI 的 Advisor 机制很适合干这事——写一个自定义 Advisor,每次调用自动记日志。

记什么日志

// 每次调用至少记: log.info("chat sessionId={} q={} model={} tokens={} costMs={}", sessionId, q, model, totalTokens, elapsedMs); // 别把完整 Prompt 打进日志(可能含用户隐私) // 敏感字段脱敏后再记

数据安全:什么能发给模型,什么不能

发给大模型的内容,等于传到第三方服务器。客户身份证号、银行卡、公司机密、未公开财报,不能直接拼进 Prompt 发给模型。能脱敏就脱敏("138****1234"),能走本地模型就走本地。合规这根弦,做 ToB 产品时必须绷紧。

Token 超限怎么办

每个模型都有上下文窗口上限(比如 128K token)。你塞进去的文档太长、对话历史太多,就报 context length exceeded。解决:① RAG 检索时只取最相关的几段,别把整个文档塞进去;② 对话历史做摘要截断;③ 超大文档先切块再按需检索。