ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

AI应用底座:从Demo到生产,基于JDK 21与Spring Cloud的工程化实践

2026/10/7 14:21:41 拓冰建站 浏览量
AI应用底座:从Demo到生产,基于JDK 21与Spring Cloud的工程化实践 1. 从一个真实困境说起为什么能跑通的AI Demo和能上线的AI系统之间隔着一道鸿沟过去一年多我参与过好几个企业内部的AI落地项目从智能客服到文档问答从合同要素抽取到工单自动分类。几乎每一个项目都经历过同样的剧本第一周搭出一个Demo效果惊艳业务方拍手叫好第二周开始讨论上线问题像潮水一样涌出来——模型调用怎么统一管理不同部门的密钥怎么隔离调用量突然翻十倍账单谁来兜底某个供应商接口挂了业务是不是直接瘫历史对话记录怎么存、怎么审计、怎么追溯这些问题没有一个是模型本身的问题全是工程问题。而绝大多数团队在Demo阶段根本没考虑过这些于是上线时间从两周变成两个月最后不了了之。QuickBlue 就是在这个背景下进入我视野的。它给自己的定位是AI 应用底座说白了就是把AI应用从Demo到生产之间那些脏活累活提前做成一套标准化的基础设施。你可以把它理解成AI时代的Spring Cloud——当年微服务刚兴起时大家也是各自造轮子直到Spring Cloud把服务注册、配置中心、熔断限流、网关路由这些通用能力沉淀下来整个行业才真正跑起来。QuickBlue想做的就是AI应用领域里同样的事情。这篇文章不打算写成产品说明书。我想从一个一线工程师的视角把AI应用底座这个概念拆开揉碎它到底解决什么问题、内部大概是怎么设计的、基于JDK 21和Spring Cloud这套技术栈能玩出什么花样、以及如果你要自己搭一个类似的底座哪些坑是绕不过去的。适合正在做AI应用落地的后端工程师、架构师也适合想搞清楚AI工程化到底在工程什么的同学。2. 拆解AI应用底座它到底该管哪些事2.1 先想清楚AI应用和传统业务系统的本质差异在哪要理解底座的价值得先理解AI应用和传统CRUD系统到底哪里不一样。我总结下来有四个核心差异每一个都会衍生出一堆工程需求。第一依赖外部不确定性。传统系统调用数据库、调用内部服务延迟和成功率基本可控。但AI应用要调用大模型API这个调用是跨公网的、按量计费的、有速率限制的、还可能因为对方模型版本更新导致输出行为变化。你没法像对待内部服务那样假设它永远稳定。第二成本是动态的、可爆炸的。传统系统的服务器成本相对固定扩容是线性的。AI应用的成本和token消耗直接挂钩一个死循环的Agent、一次prompt注入攻击、一个被爬的接口都可能让账单在几小时内翻几十倍。成本控制必须是底座的一等公民而不是事后加个监控。第三数据敏感性和合规要求高。用户和AI的对话里可能包含个人信息、商业机密。这些数据往哪存、存多久、谁能看、怎么脱敏都是硬性要求。而且不同模型供应商的数据处理政策不一样企业往往需要数据不出境敏感信息不进第三方这类策略。第四能力是组合出来的。一个完整的AI应用往往不是调一次模型就完事而是RAG检索、多轮对话、工具调用、结果校验、人工兜底这一长串流程的组合。这些环节需要被编排、被观测、被复用。把这四点摆出来AI应用底座要管什么就清楚了它要屏蔽外部依赖的不确定性、控制动态成本、满足数据合规、支撑能力编排。QuickBlue这类产品的价值就在于把这四件事做成开箱即用的能力而不是让每个业务团队重复造轮子。2.2 一个合格的AI底座至少要覆盖这五层能力我把AI应用底座的能力拆成五层从下往上说。最底层是模型接入层。它要统一不同供应商的API差异——OpenAI风格、Claude风格、国产模型风格各不相同请求格式、流式返回格式、错误码都不一样。底座要做的是提供一套统一的抽象接口业务代码只面向这套接口编程换供应商时改配置而不是改代码。同时这一层还要处理密钥管理、多租户隔离、请求重试、超时控制。往上是流量治理层。这是Spring Cloud生态最擅长的部分。限流防止某个租户打爆配额、熔断某个模型供应商挂了自动降级到备用、负载均衡多个API Key轮询、灰度新模型小流量验证。这些能力在微服务领域已经非常成熟直接迁移到AI场景即可。再往上是能力编排层。也就是常说的Chain、Agent、Workflow。把检索-拼接prompt-调用模型-解析结果-调用工具这一串步骤编排起来支持条件分支、循环、并行。这一层决定了业务开发的效率。然后是数据与记忆层。对话历史、向量知识库、用户偏好、会话状态都要有统一的存储和检索方案。还要处理上下文窗口管理——对话太长怎么截断、怎么摘要、怎么保留关键信息。最上层是可观测与治理层。全链路追踪一次请求经过了哪些环节、每步耗时多少、成本统计按租户、按应用、按模型维度、内容审计输入输出留痕、敏感词过滤、质量评估回答准确率、幻觉率。这五层不是每层都要自研很多可以基于开源组件拼装。但关键是要有一个统一的底座把它们串起来否则就是一堆散装组件运维和排障时你会想哭。2.3 为什么是底座而不是框架或平台这里有个概念区分很重要。框架是给开发者用的比如LangChain它帮你写代码更方便但部署、运维、治理它不管。平台通常是给业务人员用的比如各种低代码AI搭建工具可视化拖拽但灵活性和可控性受限。底座介于两者之间它对开发者暴露API和SDK保持编程的灵活性同时它又内置了生产环境必需的治理能力让开发者不用自己操心。用一句话概括框架解决怎么写平台解决怎么搭底座解决怎么稳。企业为什么需要底座因为当你有三个以上的AI应用要上线时你会发现每个应用都在重复实现限流、重试、密钥管理、日志埋点。这时候要么容忍重复劳动和标准不一要么抽一层公共底座出来。QuickBlue瞄准的就是后者的需求。3. 技术选型背后的逻辑JDK 21 Spring Cloud 这套组合拳3.1 为什么是JDK 21而不是JDK 17或JDK 8先说JDK版本这个事。很多企业还在JDK 8上跑升级动力不足。但AI应用底座这个场景JDK 21有几个特性是实打实有用的。虚拟线程Virtual Threads是最大的理由。AI应用的典型特征是大量IO等待——等模型返回、等向量检索、等工具调用。传统线程模型下一个请求占一个线程线程池打满后新请求就得排队。虚拟线程让一个请求一个线程的编程模型重新变得可行同时底层用少量载体线程支撑海量并发。实测下来在模型调用这种高延迟场景虚拟线程能把吞吐量提升一个数量级而代码几乎不用改。结构化并发Structured Concurrency在编排场景很有用。比如一个请求要并行调用三个模型然后聚合结果用结构化并发可以保证子任务的生命周期被正确管理异常传播清晰不会出现主任务结束了子任务还在跑的泄漏。模式匹配和Record让代码更简洁尤其是处理各种请求响应DTO时Record的不可变性和自动生成的equals/hashCode能省不少事。当然升级JDK 21也有代价部分老依赖可能不兼容GC调优需要重新做。但如果是从零搭底座我强烈建议直接上21别在17上纠结。3.2 Spring Cloud在AI场景的适配与改造Spring Cloud这套微服务全家桶放到AI场景需要做一些适配。服务注册与发现这块基本可以直接用。AI底座本身也是微服务架构模型网关、编排引擎、向量服务、审计服务各自独立部署通过注册中心互相发现。配置中心要特别设计。AI应用的配置变化很频繁——模型版本切换、prompt模板调整、限流阈值修改。这些配置需要支持热更新、灰度发布、按租户覆盖。用Nacos或Apollo都能做关键是要设计好配置的层级结构全局默认 应用级 租户级 会话级。网关是重中之重。所有模型调用都应该经过网关网关负责鉴权、限流、计费埋点、请求改写、响应过滤。Spring Cloud Gateway基于响应式模型配合虚拟线程要注意线程模型的混用问题这块后面细说。熔断限流用Sentinel。但要注意AI场景的限流维度比传统服务复杂按租户限、按模型限、按token量限、按并发数限。Sentinel的规则配置需要扩展而且限流后的降级策略也要设计——是返回缓存结果、切换到小模型、还是直接排队。分布式事务在AI场景相对弱化因为大部分操作是幂等的读操作。但涉及计费扣减、配额扣减时还是需要保证一致性可以用Seata或者简单的本地消息表方案。3.3 微服务拆分AI底座该怎么切微服务拆分是个老话题但AI底座有它的特殊性。我建议按能力维度而不是业务维度来拆。一个参考的拆分方案服务名职责拆分理由模型网关服务统一模型接入、协议转换、密钥管理所有调用必经独立扩缩容编排引擎服务Chain/Agent/Workflow执行计算密集需要独立资源池向量检索服务向量化、索引、相似度检索依赖专用存储独立部署会话记忆服务对话历史、上下文管理读写频繁需要缓存层计费配额服务用量统计、配额扣减强一致要求独立事务边界审计服务内容留痕、敏感词过滤合规要求异步处理管理控制台配置管理、监控展示面向运维独立发布拆分的粒度要控制好。我见过有团队把每个模型供应商都拆成一个服务结果服务数量爆炸运维成本极高。合理的做法是按能力拆供应商差异用策略模式在网关内部消化。另外微服务拆分后服务间的调用链路变长一次AI请求可能经过五六个服务。这时候全链路追踪就不是可选项而是必需品。TraceId要贯穿整个链路每个环节的耗时、输入输出都要能查到。4. 落地实操从零搭一个最小可用的AI底座4.1 环境准备与依赖版本锁定假设我们要搭一个最小可用的底座验证核心链路。环境准备这块版本兼容性是第一个坑。我的建议版本组合JDK 21LTS虚拟线程稳定Spring Boot 3.2.x对JDK 21支持完善Spring Cloud 2023.0.x对应Spring Boot 3.2Spring Cloud Alibaba 2023.0.xNacos、SentinelNacos 2.3.x注册中心配置中心Sentinel 1.8.x流量治理这里有个坑要提醒Spring Cloud Alibaba的版本必须和Spring Cloud版本严格对应版本错配会导致启动时各种Bean找不到。我踩过一次排查了大半天最后发现是版本表没对齐。建议直接查官方版本对应关系表别凭感觉选。Maven依赖里虚拟线程的开启很简单在配置里加一行spring: threads: virtual: enabled: true但要注意开启虚拟线程后某些依赖synchronized块的库会出现pin住载体线程的问题导致性能反而下降。JDK 21里可以用-Djdk.tracePinnedThreadsfull来排查。常见的坑点是老版本的数据库连接池和某些JSON库升级到最新版基本能解决。4.2 模型网关的核心设计统一抽象与协议转换模型网关是整个底座的心脏。它的核心职责是把N种供应商的API抽象成1套内部协议。内部协议我建议设计成这样的结构public record ChatRequest( String tenantId, String appId, String sessionId, ListMessage messages, ModelConfig config, MapString, Object metadata ) {} public record ChatResponse( String requestId, String content, Usage usage, String model, MapString, Object raw ) {}供应商适配用策略模式。每个供应商实现一个ModelProvider接口负责把内部协议转成供应商协议再把响应转回来。新增供应商时只需要加一个实现类不改动核心逻辑。public interface ModelProvider { String name(); ChatResponse chat(ChatRequest request); FluxChatResponse stream(ChatRequest request); boolean supports(String modelName); }流式返回是个难点。不同供应商的SSE格式不一样有的用data:前缀有的用自定义事件。网关要统一成一种格式再往下游推。这里建议用Reactor的Flux配合WebFlux做流式转发。但要注意WebFlux和虚拟线程不要混用WebFlux本身是事件循环模型虚拟线程是阻塞模型的补充两者混用容易出问题。我的做法是网关的流式接口用WebFlux非流式接口用虚拟线程阻塞式编程各管各的。密钥管理这块千万别把API Key硬编码在配置文件里。建议用配置中心加密存储或者对接KMS。多租户场景下每个租户的密钥要隔离网关根据tenantId动态选择密钥。密钥轮换要支持不停机。4.3 用Sentinel做多维度限流按租户、按模型、按TokenSentinel默认的限流维度是资源和来源放到AI场景不够用。我们需要扩展。按租户限流把tenantId作为限流参数。Sentinel支持热点参数限流可以针对特定参数值配置规则。Entry entry SphU.entry(model-chat, EntryType.IN, 1, tenantId);然后在Sentinel控制台配置热点规则针对tenantId这个参数不同租户可以有不同的QPS阈值。按模型限流不同模型的成本和速率限制不同需要独立限流。可以把模型名拼进资源名比如model-chat:gpt-4。按Token量限流这个Sentinel原生不支持需要自己实现。思路是在网关层统计每个租户的token消耗用滑动窗口算法计算速率超过阈值就拒绝。可以用Redis的ZSET做滑动窗口或者用Redisson的RateLimiter。限流后的降级策略也要设计。我的建议是分级租户级超限直接拒绝返回429模型级超限切换到备用模型比如从大模型切到小模型全局超限进入排队队列返回处理中这里有个经验降级策略要可配置而且要有开关。线上出问题时能一键关闭降级避免降级逻辑本身出bug导致更大故障。4.4 会话记忆与上下文窗口管理对话历史管理看似简单实则坑很多。核心问题是上下文窗口有限但对话可能很长。常见的处理策略有三种滑动窗口只保留最近N轮对话。简单粗暴但会丢失早期的重要信息。摘要压缩把早期对话用模型总结成一段摘要拼在prompt里。效果好但增加一次模型调用有成本。向量检索把历史对话向量化存起来每次根据当前问题检索相关片段。适合长对话但实现复杂。我的建议是组合使用近期对话用滑动窗口保留原文远期对话用摘要压缩特别重要的信息比如用户明确说的偏好单独抽取存结构化字段。存储这块会话数据建议用Redis做热存储定期落库到MySQL或MongoDB。Redis的key设计要包含tenantId和sessionId方便隔离和清理。TTL要设置避免无限增长。上下文拼接时要注意token计算。不同模型的tokenizer不一样不能简单按字符数估算。建议用对应模型的tokenizer库精确计算或者用tiktoken这类工具。拼接时要留出输出token的预算别把窗口占满了导致模型没空间回答。5. 踩坑实录那些文档里不会写的教训5.1 虚拟线程与synchronized的pin住陷阱前面提过虚拟线程的pin问题这里展开说。虚拟线程在遇到synchronized块时如果块内有阻塞操作会pin住载体线程导致载体线程无法被其他虚拟线程复用。如果大量虚拟线程都pin住性能会退化到比传统线程还差。我遇到的具体场景是某个老版本的HTTP客户端内部用了synchronized在虚拟线程里调用时并发一上来就卡死。排查过程是这样的先用jdk.tracePinnedThreads打出pin住的堆栈定位到具体是哪个库然后查这个库的版本发现新版本已经用ReentrantLock替换了synchronized升级后问题解决。经验总结上虚拟线程前先做依赖审计把所有涉及并发的老库升级到最新版。JDK官方有个pin排查工具建议在压测阶段就打开别等上线后才发现。5.2 流式响应的背压与超时处理流式返回SSE在AI场景很常见但背压处理是个难点。如果下游消费慢上游还在猛推数据内存会堆积。Reactor的Flux本身支持背压但要注意几点一是要设置合理的buffer大小太小会频繁触发背压信号太大会占内存二是要处理客户端断连客户端断开后要及时取消上游订阅否则模型还在生成白白消耗token三是要设置整体超时流式响应可能持续很久要有最大时长限制。我踩过的坑是客户端断连后网关没有及时取消上游调用导致模型继续生成账单白白增加。后来加了doOnCancel回调在取消时主动关闭上游连接问题解决。5.3 多租户隔离的边界哪些必须隔离哪些可以共享多租户隔离不是越彻底越好过度隔离会增加成本和复杂度。我的经验是分三类处理必须隔离的API密钥、配额、计费数据、敏感对话内容。这些涉及安全和商业利益必须严格隔离。可以共享的模型连接池、向量索引如果数据不敏感、公共prompt模板。共享能降低成本。需要权衡的日志和监控数据。完全隔离便于排查但存储成本高共享则要注意脱敏。实现上隔离可以用逻辑隔离同一套服务数据带tenantId或物理隔离独立部署。大部分场景逻辑隔离够用只有对合规要求极高的客户才需要物理隔离。逻辑隔离的关键是每个数据访问层都要强制带tenantId条件建议用MyBatis拦截器或JPA的过滤器统一处理避免漏写。5.4 成本失控的几种典型场景与防御成本失控是AI应用最怕的事。我见过几种典型场景场景一死循环Agent。Agent调用工具后判断需要再调用结果陷入循环。防御设置最大迭代次数超过就强制终止。场景二prompt注入导致超长输出。攻击者构造特殊输入让模型生成超长内容。防御设置max_tokens上限输出超长直接截断。场景三接口被爬。外部恶意调用消耗配额。防御鉴权限流异常调用模式检测。场景四缓存失效导致重复调用。相同问题反复调用模型。防御对确定性请求做结果缓存相同输入直接返回缓存。这些防御措施都应该在底座层统一实现而不是让业务团队各自处理。QuickBlue这类底座的价值很大一部分就体现在这里。6. 底座之上AI应用还能怎么演进6.1 从调用模型到编排能力有了底座之后业务开发的范式会发生变化。以前是我要调模型我得自己处理限流重试现在是我声明我要什么能力底座负责调度。比如一个合同审查应用它需要的能力是OCR识别、要素抽取、条款比对、风险评级。这些能力在底座上注册后业务代码只需要编排先OCR再抽取然后并行做比对和评级最后聚合。底座的编排引擎负责执行、重试、降级。这种模式下业务团队专注业务逻辑底座团队专注基础设施分工清晰。6.2 可观测性AI应用的黑盒怎么打开AI应用最大的痛点是不可解释。用户问为什么这么回答你很难说清楚。底座要做的是把黑盒尽量打开。全链路追踪要记录输入prompt是什么、检索到了哪些文档、模型返回的原始内容、经过后处理后的最终输出。这样出问题时能完整复现。质量评估要持续做定期抽样用人工或模型评估回答质量统计准确率、幻觉率。这些指标要能按应用、按模型、按时间维度查看。成本归因要精确每个请求消耗多少token、花了多少钱要能归到具体租户和应用。这样才能做成本优化。6.3 未来可能的扩展方向从技术演进看AI底座还有几个方向可以走。多模态支持现在主要是文本未来图片、音频、视频的接入会越来越多。底座要抽象出统一的多模态接口。边缘推理部分场景下模型推理要下沉到边缘减少延迟和带宽。底座要支持云端和边缘的统一调度。模型微调与私有化企业对数据安全的要求越来越高私有化部署和微调需求会增加。底座要支持训练任务的编排和模型版本管理。Agent生态当Agent成为主流底座要提供Agent的注册、发现、协作机制类似微服务的服务治理。这些方向不一定都要现在做但架构设计时要留好扩展点。比如模型接入层的抽象要足够通用不要写死成只支持文本。7. 我个人的一些实践体会做AI应用底座这件事技术难度其实不是最大的最大的挑战是平衡通用性和灵活性。做得太通用业务方觉得不好用绕开底座自己搞做得太定制又失去了底座的意义变成给某个业务做的专用系统。我的经验是底座只做那些所有AI应用都绕不开的事——模型接入、限流、计费、审计、追踪。这些是刚需业务方没有理由自己重复实现。至于编排、RAG这些可以提供参考实现但允许业务方自己选型不要强制。另一个体会是底座要能渐进式接入。不要指望业务方一次性全量迁移要允许他们先用底座的一部分能力比如先接入模型网关其他照旧。等尝到甜头了再逐步接入更多。强制迁移只会引发抵触。最后说个具体的日志和追踪的埋点一定要在底座层做而且要做得足够细。我见过太多团队上线后出问题发现日志里只有调用失败没有任何上下文排查全靠猜。底座层把traceId、租户、应用、模型、耗时、token量这些信息统一埋好能省下大量排障时间。这个投入绝对值。