1. 为什么“AI 微服务开发平台”会成为企业落地的刚需
1.1 从“能跑通 Demo”到“能扛住生产”之间的鸿沟
过去一年多,我接触过不少团队做 AI 应用,场景五花八门:智能客服、知识库问答、合同审查、工单自动分类、报表解读。几乎所有人都会经历同一个阶段——用 Python 写个脚本,调一下大模型接口,本地跑通,效果惊艳,然后老板说“上线吧”。接着问题就来了:并发一上来接口超时、模型调用费用失控、会话状态丢失、多个业务线各写一套重复代码、日志散落各处没法排查、权限和数据隔离全靠口头约定。
这就是“Demo 能跑”和“生产可用”之间的鸿沟。Demo 关注的是单次调用能不能出结果,生产关注的是稳定性、可观测性、成本、权限、扩展性、多团队协作。这两件事的工程复杂度差了一个数量级。
一个面向生产环境的原生 AI 微服务快速开发平台,本质上就是来填这条鸿沟的。它把 AI 能力(大模型调用、向量检索、Agent 编排、提示词管理)和微服务工程能力(服务注册发现、配置中心、网关、熔断限流、链路追踪)揉在一起,给企业一套可以直接当“底座”用的东西。你不需要从零搭脚手架,而是站在一个已经考虑过生产问题的框架上做业务。
1.2 谁最需要这类平台
我把潜在使用者分成三类,你可以对号入座。
第一类是中大型企业的内部研发团队。他们有多个业务系统,想把 AI 能力嵌进去,但不想每个系统各自为战。他们需要统一的大模型接入层、统一的鉴权和配额、统一的可观测性。这类团队最看重的是“规范”和“可治理”。
第二类是创业公司或小团队。人少事多,没有专职的架构师,希望一套代码既能快速验证想法,又能在验证成功后平滑扩容。他们最看重的是“开箱即用”和“少踩坑”。
第三类是传统行业的技术负责人,比如制造、能源、政务信息化背景的团队。他们对微服务有一定认知,但对 AI 工程化不熟,需要一个把两边都照顾到的参考实现。他们最看重的是“文档清楚”和“有现成的最佳实践”。
这三类人的共同点是:都不想重复造轮子,都希望把精力放在业务逻辑和效果调优上,而不是基础设施。这个平台的价值就在这里。
1.3 技术选型背后的取舍逻辑
标题里点出的几个关键词——JDK 21、Spring Cloud、Vue 3——不是随便凑的,每一个都对应着明确的工程考量。
选 JDK 21,核心原因是虚拟线程(Virtual Threads)正式转正。AI 应用的一个典型特征是大量 IO 等待:等大模型返回、等向量库查询、等外部工具调用。传统线程池模型下,一个请求占一个线程,高并发时线程池很快被打满,你只能靠加机器或者做复杂的异步编排。虚拟线程让“一个请求一个线程”的简单写法也能扛住高并发,代码可读性和吞吐量兼得。另外 JDK 21 在 ZGC、模式匹配、Record 等方面的成熟度也足够支撑生产。
选 Spring Cloud 体系,是因为它在国内企业里的认知度和生态最厚。服务注册发现、配置中心、网关、负载均衡、熔断限流,这些组件企业里的运维和开发都熟。虽然社区里一直有“Spring Cloud Alibaba 某些组件停更”的讨论,但核心的 Spring Cloud 抽象层依然活跃,而且很多团队已经在上面投了资,迁移成本高。平台基于 Spring Cloud 做封装,等于顺着企业现有的技术栈走,落地阻力最小。
选 Vue 3,是因为前端要处理大量交互式场景:对话流、Agent 编排画布、知识库管理、监控看板。Vue 3 的组合式 API 在逻辑复用和类型推导上比 Vue 2 舒服很多,配合 Vite 构建速度快,适合快速迭代的中后台产品。
提示:技术选型没有绝对的对错,只有适不适合你的团队。如果你的团队全是 Python 背景,硬上 Java 微服务反而会增加沟通成本。选型的第一原则是“团队能维护”。
2. 平台整体架构与核心模块拆解
2.1 分层架构:把 AI 能力和工程能力解耦
一个能上生产的平台,架构上一定要分层清晰。我理解的合理分层是这样的:
- 接入层:统一网关,负责路由、鉴权、限流、请求日志。所有外部流量从这里进。
- 应用层:各个业务微服务,比如对话服务、知识库服务、Agent 服务、工作流服务。每个服务职责单一,可以独立部署和扩容。
- AI 能力层:把大模型调用、向量化、检索、重排、提示词渲染这些能力抽象成独立的服务或 SDK。业务服务不直接依赖某一家模型厂商,而是依赖这一层。
- 基础设施层:注册中心、配置中心、消息队列、缓存、数据库、对象存储、向量数据库。
- 可观测层:日志、指标、链路追踪,横跨所有层。
这样分的好处是:换模型厂商时只动 AI 能力层;业务逻辑变化时只动应用层;基础设施升级时上层基本无感。解耦带来的维护性提升,在项目跑过半年之后会非常明显。
2.2 核心模块清单与职责
我把这类平台的核心模块列成一张表,方便你对照自己的需求。
| 模块 | 核心职责 | 关键技术点 |
|---|---|---|
| 统一网关 | 路由转发、鉴权、限流、灰度 | Spring Cloud Gateway、JWT、Sentinel |
| 模型接入 | 多厂商模型统一调用、失败重试、费用统计 | 适配器模式、异步调用、Token 计数 |
| 提示词管理 | 模板存储、版本管理、变量渲染 | 模板引擎、版本快照 |
| 知识库 | 文档解析、切分、向量化、检索 | 向量数据库、Embedding、重排 |
| Agent 编排 | 工具调用、多步推理、状态管理 | 状态机、函数调用协议 |
| 工作流 | 可视化编排、节点执行、条件分支 | DAG 引擎、异步任务 |
| 会话管理 | 多轮上下文、会话隔离、历史存储 | Redis、上下文窗口裁剪 |
| 可观测 | 日志聚合、指标采集、链路追踪 | OpenTelemetry、Prometheus |
| 权限体系 | 用户、角色、租户、数据隔离 | RBAC、多租户 |
这张表不是让你一次全做完,而是给你一个全景图。实际落地时,建议先做网关、模型接入、会话管理这三块,把最小闭环跑通,再逐步加知识库和 Agent。
2.3 微服务拆分粒度:别为了拆而拆
微服务拆分是很多团队容易走极端的地方。拆得太细,服务间调用链变长,排查问题像破案;拆得太粗,又失去了独立部署和扩容的意义。
我的经验是,AI 应用按“能力边界”拆,而不是按“技术分层”拆。比如“对话”是一个能力,“知识库检索”是一个能力,“Agent 执行”是一个能力,它们各自可以独立成服务。但“用户管理”和“权限校验”就没必要拆成两个服务,放一起更合理。
一个实用的判断标准:如果两个模块的扩容节奏不同、发布频率不同、或者对稳定性的要求不同,就考虑拆开。否则先放一起,等真的痛了再拆。过早拆分带来的分布式事务、跨服务调试、数据一致性成本,往往比收益大。
注意:拆分前先想清楚数据边界。哪些数据是某个服务独有的,哪些是共享的。共享数据尽量通过接口获取,而不是多个服务直接读同一张表,否则后期改表结构会牵一发动全身。
3. 关键环节的实操要点与参数设计
3.1 模型接入层的统一抽象怎么做
模型接入层是整个平台最容易被低估的部分。很多人觉得不就是调个 HTTP 接口吗?但生产环境要考虑的事情很多:不同厂商的请求格式不一样、返回格式不一样、错误码不一样、流式输出的协议不一样、计费方式不一样。如果业务代码里到处散落着if 厂商 == A这种判断,维护会非常痛苦。
合理的做法是定义一个统一的接口,比如:
public interface ChatModel { ChatResponse chat(ChatRequest request); Flux<ChatChunk> stream(ChatRequest request); }然后每个厂商写一个适配器实现这个接口。业务层只依赖ChatModel,通过配置决定用哪个实现。这样换厂商、加厂商、做 A/B 测试都很方便。
参数设计上有几个关键点。第一是超时时间,大模型调用普遍比普通接口慢,建议连接超时设 5 秒,读取超时设 60 到 120 秒,流式场景可以更长。第二是重试策略,只对网络错误和 5xx 重试,对 4xx 不重试,重试次数 2 到 3 次,并且要加退避。第三是并发控制,每个厂商的配额不同,用信号量或令牌桶限制并发,避免触发限流。
费用统计也建议在这一层做。每次调用记录输入 Token 数、输出 Token 数、模型名称、耗时,落到一张明细表里。月底按业务线、按用户聚合,成本一目了然。这个功能在早期没人重视,等账单来了才想起来做就晚了。
3.2 会话上下文管理的取舍
多轮对话的核心是上下文管理。最简单的做法是把历史消息全带上,但 Token 会线性增长,成本和延迟都受不了。所以必须做上下文裁剪。
常见的策略有三种。第一种是滑动窗口,只保留最近 N 轮对话。实现简单,但会丢失早期的重要信息。第二种是摘要压缩,把早期对话用模型总结成一段话,替代原始消息。效果好但多一次模型调用。第三种是向量召回,把历史消息存进向量库,每轮根据当前问题召回相关历史。适合长对话和知识密集型场景。
我的建议是组合使用:近期对话用滑动窗口保留原文,远期对话做摘要或向量召回。窗口大小根据模型上下文长度定,比如模型支持 128K,你留 8K 给近期对话,2K 给摘要,剩下的给知识库检索结果和系统提示词。
会话隔离也要注意。不同用户的会话必须严格隔离,用userId + sessionId作为 Redis 的 key 前缀。同一用户的不同会话也要隔离,避免串话。这些看起来是小事,但线上出过一次串话事故,用户信任度会大打折扣。
3.3 知识库检索的完整链路
知识库是很多企业 AI 应用的核心。完整链路是:文档上传、解析、切分、向量化、存储、检索、重排、拼接进提示词。
文档解析要处理多种格式:PDF、Word、Excel、PPT、Markdown、HTML。PDF 里的表格和图片是难点,纯文本提取往往丢信息。如果预算允许,可以用带版面分析的解析方案;预算有限就先用基础解析,把表格单独处理。
切分策略直接影响检索效果。切太大,检索出来的内容冗余,浪费 Token;切太小,语义不完整,检索不准。一般建议按语义切分,比如按段落或标题层级,单块控制在 300 到 800 字。块之间留一点重叠,避免边界信息丢失。
向量化要选合适的 Embedding 模型。中文场景下,建议选在中文语料上表现好的模型。维度不是越高越好,高维度检索慢、存储贵,效果提升未必明显。768 或 1024 维在多数场景够用。
检索阶段,先用向量相似度召回 Top K(比如 20 条),再用重排模型精排取 Top N(比如 5 条)。重排能显著提升相关性。最后把这几条拼进提示词,附上来源,方便用户核对。
提示:知识库效果不好,八成问题出在切分和解析,而不是模型。先花时间把文档处理干净,比换更贵的模型更有效。
3.4 网关限流与熔断的参数怎么定
网关是流量的入口,限流和熔断配置不合理,要么保护不了后端,要么误伤正常用户。
限流建议分两个维度:全局 QPS 限流和单用户 QPS 限流。全局限流保护整个系统不被压垮,单用户限流防止个别用户刷接口。全局阈值根据压测结果定,一般是系统容量的 70% 到 80%。单用户阈值根据业务定,比如普通用户 5 QPS,VIP 用户 20 QPS。
熔断针对下游服务。当某个服务的错误率超过阈值(比如 50%)或慢调用比例过高时,自动熔断一段时间,期间请求快速失败,避免雪崩。熔断时间一般设 10 到 30 秒,然后进入半开状态试探恢复。
这些参数没有标准答案,必须结合压测和线上监控持续调整。建议先把阈值设保守一点,观察一段时间再放宽,而不是一上来就设得很激进。
4. 常见问题排查与避坑经验
4.1 典型问题速查表
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 接口偶发超时 | 模型侧抖动、网络波动 | 看模型调用耗时分布,加重试和降级 |
| 流式输出中断 | 网关缓冲、连接超时 | 关闭网关响应缓冲,调大超时 |
| 上下文串话 | 会话 key 设计不当 | 检查 key 是否含用户和会话标识 |
| 检索结果不相关 | 切分粒度、Embedding 模型 | 抽样看切分块,换模型对比 |
| 内存持续增长 | 上下文未释放、缓存无过期 | 检查缓存 TTL 和对象引用 |
| 费用异常升高 | 上下文过长、重复调用 | 看 Token 明细,优化裁剪策略 |
| 服务注册不上 | 网络、配置、版本不匹配 | 看注册中心日志和心跳 |
这张表是我在实际项目中反复遇到的,你可以先收藏,出问题时按图索骥。
4.2 几个容易踩的坑
第一个坑是忽视流式输出的网关配置。很多网关默认会缓冲响应,导致流式输出变成“憋一大段再吐出来”,用户体验很差。解决方法是针对流式接口关闭缓冲,并确保超时时间足够长。
第二个坑是上下文没有做长度保护。用户输入超长文本,或者多轮对话累积,很容易超过模型上下文限制,导致调用失败。一定要在拼接提示词前做长度校验,超了就裁剪或拒绝。
第三个坑是向量库和业务库的数据一致性。文档删除了,向量库里的向量没删,检索时还会召回已删除内容。建议用消息队列做异步同步,并加定期对账任务。
第四个坑是权限校验只做在网关。网关校验了用户身份,但服务间调用时没有传递身份,导致下游服务无法做数据隔离。建议在请求头里透传用户和租户信息,下游服务据此过滤数据。
第五个坑是日志里打印了敏感信息。提示词和模型返回里可能包含用户隐私或商业数据,日志脱敏没做好会带来合规风险。建议在日志框架里加脱敏规则,对手机号、身份证、邮箱等自动打码。
4.3 性能优化的几个实用手段
模型调用是最大的耗时来源,优化空间也最大。第一,能并行就并行。比如同时查知识库和调工具,用CompletableFuture或响应式编程并行执行,总耗时取最长的那个而不是累加。第二,能缓存就缓存。相同的问题和上下文,结果可以缓存一段时间,尤其是 FAQ 类场景。第三,能流式就流式。首字延迟比总耗时更影响体感,流式输出让用户更快看到内容。
JVM 层面,JDK 21 的虚拟线程对 IO 密集型场景提升明显,但要注意别在虚拟线程里做 CPU 密集操作,也别用synchronized包裹阻塞调用,否则会 pin 住载体线程。用ReentrantLock替代。
数据库层面,会话历史和调用明细这类写多读少的数据,考虑用分表或时序数据库。向量检索用专门的向量库,别硬塞进关系库。
5. 从零搭建的最小可行路径
5.1 第一阶段:跑通最小闭环
如果你现在就想动手,我建议按这个顺序来。
先搭注册中心和配置中心,这是微服务的地基。然后起一个网关,配好路由和鉴权。接着写模型接入服务,先接一家模型,把同步和流式都跑通。再写会话服务,用 Redis 存上下文。最后写一个简单的对话接口,从网关进来,经过会话服务,调模型接入,返回结果。
这个闭环跑通,你就有了一个能用的 AI 对话后端。前端用 Vue 3 写个简单页面,输入框加消息列表,调流式接口渲染。
5.2 第二阶段:补齐生产能力
闭环跑通后,开始补生产必需的能力。加限流熔断,加日志和链路追踪,加费用统计,加权限体系。然后接第二家模型,验证适配器抽象是否合理。再加知识库,把 RAG 链路跑通。
这个阶段的关键是“可观测”。没有日志和指标,出了问题只能猜。建议一开始就用 OpenTelemetry 做链路追踪,每个请求一个 traceId,从网关透传到模型调用,排查问题时能串起来看。
5.3 第三阶段:平台化与多租户
当有多个业务线要用时,就要考虑多租户。租户之间数据隔离、配额隔离、模型配置隔离。这时候配置中心的作用就体现出来了,不同租户可以有不同的模型和参数。
再往后可以做 Agent 编排和工作流,让业务人员通过可视化界面配置 AI 流程,而不是每次都找开发。这一步的投入产出比取决于你的业务复杂度,不是所有团队都需要。
提示:不要一上来就追求大而全。先把一个场景做深做透,跑通从开发到运维的完整流程,再复制到其他场景。平台的价值是在复用中体现的,不是在功能列表里。
6. 我个人的一些实践体会
做这类平台,技术难点其实不是最难的,最难的是“克制”。克制住把什么功能都往里塞的冲动,克制住为了技术先进性而选型的冲动,克制住过早抽象、过度设计的冲动。
我见过太多平台,功能列表很长,但每个功能都只做到 60 分,用起来到处是坑。反而不如一个功能少但每个都做到 90 分的平台,用起来顺手,团队也愿意在上面投入。
另一个体会是,文档和示例代码的重要性不亚于核心代码。一个平台能不能被团队接受,很大程度上取决于新人能不能在半天内跑起来第一个 Demo。如果文档写得含糊,示例跑不通,再好的架构也没人用。
最后,AI 领域变化快,模型、协议、工具链都在快速演进。平台设计时要留好扩展点,但不要为不确定的未来过度设计。接口抽象做好,配置外置,剩下的等真需要时再改。能快速响应变化的平台,比一开始就“设计完美”的平台更有生命力。