
1. 从一个真实困境说起为什么能跑起来的AI Demo和能上线的AI应用之间隔着一道鸿沟过去一年多我参与过好几个企业内部的AI落地项目从智能客服、文档问答到工单自动分类几乎每一个项目都经历过同样的剧本第一周搭出一个Demo效果惊艳老板拍板就按这个方向做第二周开始接入真实业务系统问题像潮水一样涌出来——模型调用超时怎么重试、多租户的密钥怎么隔离、对话上下文存在哪里、限流怎么做、灰度怎么发、日志怎么追、成本怎么核算。原本以为是个调个API的活儿最后变成了一个标准的分布式系统工程。这就是AI 应用底座这个概念出现的现实土壤。QuickBlue 正是围绕这个痛点在做的事情它不是一个模型也不是一个聊天界面而是一层位于业务应用和大模型能力之间的基础设施。你可以把它理解成AI 应用的操作系统底座——业务方只管写提示词和业务逻辑剩下的模型路由、会话管理、权限隔离、流量治理、可观测性全部由底座兜住。这篇文章我想聊清楚三件事QuickBlue 这类 AI 应用底座到底解决了什么问题它背后的技术选型为什么大概率会落在微服务、Spring Cloud、JDK 21 这条线上以及如果你要自己搭一个类似的底座哪些坑是必须提前知道的。文章会涉及不少微服务架构、服务治理、配置管理的内容适合有一定后端基础、正在做或准备做企业级 AI 应用的工程师和架构师参考。如果你只是想知道QuickBlue 是什么看完第一节和第二节基本就够了如果你想动手复现后面几节的选型和踩坑经验会更值钱。2. QuickBlue 到底是个什么东西拆开AI 应用底座这层壳2.1 底座不是中间件而是能力收敛层很多人第一次听到AI 应用底座会下意识地把它归类成某种中间件比如消息队列或者网关。这个理解不算错但不够准确。中间件通常解决的是单一维度的通用问题而 AI 应用底座解决的是AI 应用这一类系统共有的、跨维度的重复建设问题。我习惯用一个类比盖住宅楼的时候地基、承重墙、水电管网是每一栋楼都要有的但你不会每盖一栋楼就重新发明一次混凝土。AI 应用底座就是AI应用领域的地基管网——它把模型接入、会话状态、鉴权限流、审计计费这些每家公司都要做一遍的事情做成一套可复用的标准能力。QuickBlue 的定位就在这儿。它向上给业务应用提供统一的 SDK 和 API向下屏蔽不同模型供应商的差异。业务方调用的是发一条消息给某个智能体而不是调用某厂商的某个版本的某个接口。这个抽象层看起来简单但它带来的价值是巨大的换模型不用改业务代码加限流不用每个应用自己写做审计不用每个团队各自埋点。2.2 一个 AI 应用底座至少要收敛哪几类能力我把这类底座的核心能力拆成五层从下往上说模型接入层统一封装多家模型服务的调用协议处理鉴权、重试、超时、降级、流式响应。这一层的关键是适配器模式每家供应商一个 adapter上层只认统一接口。会话与上下文层管理多轮对话的上下文包括短期记忆当前会话窗口和长期记忆向量检索。这一层要解决上下文裁剪、token 预算、会话隔离的问题。治理层限流、熔断、灰度、路由。AI 应用的流量特征和传统 Web 差别很大——单次请求耗时长、token 消耗是核心成本指标、突发流量容易打爆下游模型配额所以治理策略要专门设计。可观测层链路追踪、token 计量、成本归因、效果评估。没有这一层你根本不知道钱花在哪、哪个智能体在拖后腿。应用编排层把提示词、工具调用、知识库检索编排成可配置的工作流让业务方不写代码也能调整 AI 行为。QuickBlue 这类产品的竞争力本质上就是这五层收敛得够不够干净、扩展点留得够不够合理。收敛得太死业务方觉得束手束脚收敛得太松又退化成什么都得自己写底座就失去意义了。2.3 为什么企业需要这四个字是关键词个人开发者做 AI 应用一个脚本、一个 API Key 就够了根本不需要底座。底座的价值只有在企业这个语境下才成立原因有三个第一是规模。当你有几十个业务线、上百个智能体、每天百万级调用的时候散落各处的 API Key、各自实现的限流、五花八门的日志格式会变成运维噩梦。底座的价值在于把复杂度集中到一处管理。第二是合规与安全。企业里数据不能随便出域调用要留痕权限要分级敏感内容要过滤。这些要求如果让每个业务团队自己实现几乎不可能保证一致性。底座是唯一能统一落实这些策略的地方。第三是成本。大模型调用是真金白银token 就是钱。没有统一的计量和归因你连哪个部门这个月花了多少都说不清。底座把成本可视化做出来才能谈优化。所以企业需要一个 AI 应用底座这句话翻译过来就是当 AI 应用从个人玩具变成企业生产系统的时候重复建设、安全合规、成本失控这三个问题会同时爆发而底座是应对它们的系统性答案。3. 技术选型背后的逻辑为什么是微服务、Spring Cloud 和 JDK 213.1 微服务不是赶时髦而是被 AI 负载的异构性逼出来的有人会问一个 AI 底座用单体架构不行吗早期确实可以但很快会撞墙。原因在于 AI 应用底座内部各模块的负载特征差异极大。模型接入层是 IO 密集型大量时间在等下游响应需要高并发连接会话层是有状态服务涉及会话粘性和存储访问治理层是计算密集型限流熔断的判定要低延迟可观测层是写密集型海量埋点数据要吞吐。把这四种特征完全不同的模块塞进一个进程资源配比会非常别扭——你给 IO 密集的模块配的线程池对计算密集的模块就是浪费。微服务化之后每个模块可以独立扩缩容、独立选型、独立发布。模型接入层可以横向扩到几十个实例扛并发治理层保持少量实例保证低延迟可观测层单独用高吞吐的存储。这就是微服务拆分在 AI 底座场景下的真实动机——不是为了架构图好看而是因为负载异构。3.2 Spring Cloud 生态的取舍停更传闻下的现实选择聊到 Spring Cloud绕不开一个热搜词spring cloud alibaba 停更了。这个说法其实需要澄清——准确地说是部分组件的维护节奏发生了变化社区活跃度有起伏但整个 Spring Cloud 生态并没有死。企业选型时真正要做的是把哪些组件可以放心用、哪些要准备替代方案想清楚。我的经验是分三类处理组件类别典型组件选型建议核心稳定类Spring Cloud Gateway、OpenFeign、LoadBalancer放心用社区成熟替代成本高治理增强类Sentinel、Nacos可用但关注维护状态做好版本锁定易变类各类配置中心、注册中心的具体实现抽象接口保留替换空间关键原则是在底座里对治理组件做一层薄封装业务代码只依赖自己定义的接口底层用 Sentinel 还是别的实现通过配置切换。这样即使某个组件真的停更替换成本也被限制在封装层内部不会波及业务。3.3 JDK 21 带来的实打实收益虚拟线程改变了 IO 密集服务的写法JDK 21 是 LTS 版本对 AI 应用底座来说最大的礼物是虚拟线程Virtual Threads。前面说过模型接入层是典型的 IO 密集型——一个请求大部分时间在等模型返回。传统写法要么用大量平台线程内存吃不消要么用响应式编程心智负担重、调试困难。虚拟线程把这个问题基本解决了。你可以用最朴素的一个请求一个线程的同步写法却能支撑极高的并发因为虚拟线程在阻塞时会让出底层载体线程。实测下来同样的模型接入服务从平台线程池切到虚拟线程在保持相同吞吐的前提下代码复杂度大幅下降线程池调优那套东西基本可以扔掉了。// JDK 21 虚拟线程执行器用于模型调用这类 IO 密集任务 try (var executor Executors.newVirtualThreadPerTaskExecutor()) { FutureModelResponse future executor.submit(() - modelClient.invoke(request)); // 同步等待写法简单但底层不会阻塞平台线程 return future.get(30, TimeUnit.SECONDS); }这段代码的价值在于它看起来像十年前的同步代码但并发能力接近响应式。对于团队里大部分工程师来说可维护性比炫技重要得多。3.4 一个务实的底座技术栈组合综合下来如果要落地一个 QuickBlue 这样的底座我会推荐这样一套组合运行时JDK 21充分利用虚拟线程和记录类Record简化 DTO。框架Spring Boot 3.x Spring Cloud网关用 Gateway服务调用用 OpenFeign。注册与配置Nacos 或 Consul接口层做抽象。治理Sentinel 做限流熔断注意数据源可以接 Redis 集群做集群限流。存储会话用 Redis向量用专用向量库计量数据用时序库或列存。可观测OpenTelemetry 统一埋点链路追踪 指标 日志三件套。这套组合不是唯一解但它的每个选择都有明确的理由而不是别人都用所以我也用。4. 自己动手搭一个最小可用底座从拆分到跑通的关键步骤4.1 服务拆分先想清楚边界再动手写代码微服务拆分最容易犯的错是按技术分层拆——把 Controller 拆一个服务、Service 拆一个服务。这是灾难。正确的拆法是按业务能力和数据所有权拆。对 AI 应用底座我建议的最小拆分是这样的gateway-service统一入口负责鉴权、路由、基础限流。model-adapter-service模型接入封装各家模型调用。session-service会话与上下文管理。governance-service治理策略的配置与下发。observability-service埋点收集、计量、成本归因。拆分的判断标准是如果两个模块的数据生命周期和扩缩容需求高度一致就不要拆。比如治理策略的配置和下发如果量不大完全可以并进 gateway。拆分不是越细越好每多一个服务就多一份运维成本和网络开销。4.2 用 Nacos 做配置中心时最容易忽略的命名空间隔离配置管理这块我踩过最深的坑是命名空间namespace的使用。很多团队上手就把所有配置堆在 public 命名空间开发、测试、生产环境靠 dataId 后缀区分。短期没问题一旦服务多起来配置就彻底乱了。正确做法是按环境划分命名空间按服务划分 group按功能划分 dataId。三层结构各司其职# Nacos 配置定位示例 namespace: prod-env # 环境隔离 group: model-adapter # 服务/模块隔离 dataId: model-adapter.yaml # 具体配置文件这样做的直接好处是切换环境只需要改一个 namespace 参数权限控制可以按 namespace 授予不同环境的配置物理隔离不会出现测试环境误读生产配置的事故。这个细节看起来小但在多环境多团队协作时能省掉大量沟通成本。4.3 模型接入层的适配器设计把变化关进笼子模型接入层是整个底座里变化最频繁的部分——供应商接口在变、模型版本在变、计费方式在变。设计这一层的核心思想是依赖倒置上层依赖抽象底层实现可插拔。public interface ModelProvider { String name(); ModelResponse invoke(ModelRequest request); FluxString stream(ModelRequest request); // 流式响应 } // 每个供应商一个实现通过 SPI 或 Spring 的 ConditionalOnProperty 装配 Component ConditionalOnProperty(name provider.type, havingValue vendorA) public class VendorAProvider implements ModelProvider { // 具体实现 }这样设计之后新增一个供应商只需要加一个实现类不改任何上层代码。更重要的是重试、超时、降级这些横切逻辑可以统一放在适配器外层用装饰器模式包一层所有供应商共享同一套容错策略。4.4 会话上下文管理token 预算才是真正的约束会话管理看起来简单——存个对话历史而已。但真正做起来核心约束是token 预算。模型的上下文窗口是有限的对话轮次一多历史就会超限。你需要一套裁剪策略。我的实践是三级策略滑动窗口保留最近 N 轮完整对话这是最基础的。摘要压缩超出窗口的早期对话用模型压缩成摘要保留关键信息。关键信息抽取把用户明确表达的偏好、约束比如我用中文预算不超过X抽成结构化字段永久保留。这三级的优先级从低到高token 紧张时先砍滑动窗口再砍摘要最后才动关键信息。实测下来这套策略能把长对话的 token 消耗压到原来的三分之一左右同时基本不损失体验。4.5 用 Sentinel 做集群限流时 Redis 数据源的配置要点单机限流用 Sentinel 很简单但 AI 底座通常需要集群限流——因为模型配额是全公司共享的单机限流会导致总量失控。集群限流需要把统计信息集中存储Redis 是常见选择。配置时有两个点必须注意。第一是Redis 集群模式下 Sentinel 数据源的 key 前缀要统一规划避免和其他业务冲突第二是限流规则的推送要走配置中心不能硬编码在代码里否则调整阈值要重新发版。// 集群限流数据源配置示意 Bean public SentinelRedisDataSource redisDataSource(RedisConnectionFactory factory) { SentinelRedisDataSource ds new SentinelRedisDataSource(); ds.setRedisConnectionFactory(factory); ds.setKeyPrefix(quickblue:sentinel:); // 统一前缀避免冲突 return ds; }注意集群限流的 Redis 一旦不可用限流会退化成单机模式甚至失效所以 Redis 本身要做高可用并且要有降级预案——比如 Redis 挂掉时切换到本地限流兜底宁可限得不准也不能完全不限。5. 上线之后才会暴露的问题几个真实踩坑记录5.1 流式响应和网关超时的冲突第一个坑来自流式响应。模型返回是流式的SSE但网关默认有超时时间。如果网关超时设得短长回答会被截断设得长又会占用连接资源。更麻烦的是很多网关的限流是基于请求数的而流式请求的一个请求可能持续几十秒实际资源占用远超普通请求。解决办法是对流式接口单独配置路由和超时策略并且限流维度从请求数改成并发连接数。这个调整不做高峰期会出现大量流式请求把连接池占满、普通请求被饿死的情况。5.2 上下文串号一个隐蔽但致命的问题第二个坑更隐蔽。会话隔离如果只靠 sessionId在异步、重试、多实例场景下很容易串号。我遇到过的情况是用户 A 的对话历史被拼进了用户 B 的请求里原因是重试时用了错误的上下文引用。根因在于上下文对象的传递没有做到不可变和显式传递。修复方案是把上下文封装成不可变对象随请求一路显式传递禁止用 ThreadLocal 存会话状态——虚拟线程场景下 ThreadLocal 的行为和平台线程不同更容易出问题。5.3 成本归因做晚了等于没做第三个坑是成本。我们一开始没做细粒度的 token 计量等到月底账单出来才发现某个智能体的调用量是预期的十倍。回头去查日志里只有请求量没有 token 量根本定位不到问题。教训是计量埋点必须和功能一起上线不能等。每个模型调用都要记录输入 token、输出 token、耗时、调用方标识。这些数据攒起来才能做成本归因和优化。晚做一个月就少一个月的数据优化就无从谈起。5.4 灰度发布在 AI 场景下的特殊性传统灰度是按流量比例切。但 AI 应用的效果不是二元的新版本提示词可能在某些输入上更好、某些更差。所以灰度不能只看流量比例还要对比效果指标——比如人工评分、用户反馈、任务完成率。我的做法是给灰度流量打标把效果指标按版本维度聚合达到统计显著性再决定是否全量。这套东西比传统灰度复杂但AI应用不做效果对比的灰度本质上是在赌博。6. 如果你要选型或自建我的几条实在建议聊了这么多技术和踩坑最后说几条选型层面的实在话。第一先想清楚你是用底座还是造底座。如果公司只有一两个 AI 应用直接用现成的云服务或者轻量框架就够了自建底座是过度工程。只有当 AI 应用数量上到一定规模、且对安全合规成本有硬要求时自建才划算。QuickBlue 这类产品的目标客户是后者。第二底座的扩展点比功能列表更重要。选型时别只看它现在支持多少家模型、多少种功能要看它的扩展机制是否清晰——加一个模型供应商要改多少代码加一个治理策略要不要动核心。扩展点设计得好的底座能陪你走三年设计得差的半年就得推倒重来。第三把可观测性当成一等公民。一个没有完善计量和追踪的 AI 底座等于一个没有仪表盘的飞机。功能可以慢慢加但可观测性必须从第一天就有。第四技术栈选稳定的别追新。JDK 21 是 LTSSpring Cloud 是成熟生态这些选择的价值在于出问题时有大量资料和社区支持。AI 领域本身变化已经够快了底座这层要尽量稳。我个人在实际操作中的体会是AI 应用底座这件事技术难度其实没有想象中高难的是克制——克制住把所有东西都塞进去的冲动克制住追新技术的冲动克制住过早优化的冲动。把模型接入、会话管理、治理、可观测这四件事做扎实一个底座就已经能撑起企业大部分 AI 应用场景了。剩下的交给业务方去发挥。